std::enable_if 基于可变参数模板的存在

std::enable_if based on variadic template existence

本文关键字:存在 参数 enable if std 于可变      更新时间:2023-10-16

我想创建对象创建器类,它将 ClassType 及其构造函数参数作为模板参数。

在基础知识中,我的代码如下所示:

template<typename ClassType, typename ... Args>
class ClassCreator : public ClassType
{
    std::tuple<Args ...> args_;
public:
    template <typename std::enable_if<sizeof...(Args)!=0>::type>
    ClassCreator(Args ... args) : args_(std::make_tuple(args ...)), ClassType(args ...){}
    template <typename std::enable_if<sizeof...(Args)==0>::type>
    ClassCreator() : ClassType(){}
    template <typename std::enable_if<sizeof...(Args)!=0>::type>
    ClassType getObject() const
    {
        return ClassType(std::get<sizeof...(Args)>(args_) ... );
    }
    template <typename std::enable_if<sizeof...(Args)==0>::type>
    ClassType getObject() const
    {
        return ClassType();
    }
};

std::enable_if防护,避免空tuple std::get<0>

我正在将其与示例类一起使用:

class A
{
public:
    A(){}
    A(int firstInt, int secondInt){}
};
int main()
{
    ClassCreator<A> creatorATrivial();
    ClassCreator<A, int, int> creatorA(1, 2);
    A aTrivial = creatorATrivial.getObject();
    A a = creatorA.getObject();
}

我收到很多错误。我是否正确理解sizeof...运算符?std::get<sizeof...(Args)>(args_) ...是解压缩tuple的有效方法吗?

问题在于,SFINAE 仅在替换的直接上下文中才有 n ot anerror。在这里的示例中:

template<typename ClassType, typename ... Args>
class ClassCreator : public ClassType
{
    template <typename std::enable_if<sizeof...(Args)!=0>::type>
    ClassCreator(Args ... args)

Args...不在构造函数的直接上下文中,因此替换将立即执行,并且发起的函数将是enable_if<true>::typeenable_if<false>::type,后者格式不正确。

还有这个:

return ClassType(std::get<sizeof...(Args)>(args_) ... );

格式不正确。第二个...没有要扩展的包。解决此问题的常用方法是使用索引序列技巧。对于 C++17,我们也有 std::apply ,在这种情况下将是:

return std::apply([](auto const&... elems){ return ClassType(elems...); },
    args_);
<小时 />

做一个类创建者来存储参数,然后传递它们的最简单方法是:

template <class T>
class ClassCreator {
    std::function<T()> creator;
public:
    // as improvements, add perfect forwarding
    template <class... Args,
        std::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
    ClassCreator(Args... args) {
        creator = [=]{ return T(args...); };
    }
    T getObject() const {
        return creator();
    }
};
ClassCreator<A> creatorATrivial();
ClassCreator<A> creatorA(1, 2); // no <int, int> necessary
A aTrivial = creatorATrivial.getObject();
A a = creatorA.getObject();