【问题标题】:std::enable_if based on variadic template existencestd::enable_if 基于可变参数模板存在
【发布时间】:2017-05-29 00:32:38
【问题描述】:

我想创建将 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 保护以避免std::get&lt;0&gt; 来自空tuple

我将它与示例类一起使用:

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&lt;sizeof...(Args)&gt;(args_) ... 是解压tuple 的有效方法吗?

【问题讨论】:

    标签: c++ c++11 variadic-templates sfinae


    【解决方案1】:

    问题在于 SFINAE 只是 not an e错误在替代。在您的示例中:

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

    Args... 不在构造函数的直接上下文中,因此将立即执行替换,并且启动的函数将是enable_if&lt;true&gt;::typeenable_if&lt;false&gt;::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();
    

    【讨论】:

      猜你喜欢
      • 2012-06-18
      • 1970-01-01
      • 1970-01-01
      • 2014-08-30
      • 2017-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多