【问题标题】:Select constructor through SFINAE in template arguments在模板参数中通过 SFINAE 选择构造函数
【发布时间】:2015-08-23 13:34:30
【问题描述】:

我正在尝试通过 SFINAE 选择构造函数,如下所示:

template<typename T>
class MyClass
{
public:
    template<typename C, typename = std::enable_if_t<std::is_class<C>::value>>
    MyClass(C) { }

    template<typename C, typename = std::enable_if_t<std::is_pointer<C>::value>>
    MyClass(C) { }
};

但是编译器报错如下:

错误 C2535: 'MyClass::MyClass(C)': 成员函数已定义或声明

甚至没有实例化构造函数。

我想出了一个可行但丑陋的解决方案,由于额外的未使用参数,我不想使用它:

template<typename T>
class MyWorkingClass
{
public:
    template<typename C>
    MyWorkingClass(C, std::enable_if_t<std::is_class<C>::value>* = nullptr) { }

    template<typename C>
    MyWorkingClass(C, std::enable_if_t<std::is_pointer<C>::value>* = nullptr) { }
};

这里给出一个简短的使用示例:

void* ptr = nullptr;
MyClass<int> mc1(ptr);

std::vector<int> vec;
MyClass<int> mc2(vec);

// Shall raise an error
// MyClass<int> mc2(0);

特征std::is_pointerstd::is_class 只是一个例子,原始特征更复杂。

有没有办法通过SFINAE选择构造函数而不给构造函数添加另一个参数(可能非常接近第一种方法)?

【问题讨论】:

    标签: c++ templates c++14 sfinae


    【解决方案1】:

    问题在于参数的默认值不是模板方法签名的一部分。所以你有两个template&lt;class C,class&gt;ctor(c) 相同的ctors。

    template<class T>
    struct MyClass {
      template<class C,
        std::enable_if_t<std::is_class<C>{}>* =nullptr
      >
      MyClass(C) { }
      template<class C,
        std::enable_if_t<std::is_pointer<C>{}>* =nullptr
      >
      MyClass(C) { }
    };
    

    这里我们使用依赖类型的模板值参数。它们从不冲突,因为指针模板参数的类型取决于类型参数。

    【讨论】:

      【解决方案2】:

      再添加一个(虚拟)类型模板参数:

      template <typename C
              , typename = std::enable_if_t<std::is_class<C>::value>>
      MyClass(C) { }
      
      template <typename C
              , typename = std::enable_if_t<std::is_pointer<C>::value>
              , typename = void>
      //        ~~~~~~~~~~~~~~^
      MyClass(C) { }
      

      DEMO

      【讨论】:

        【解决方案3】:

        这可能更简单:

        template<typename T>
        class MyClass {
        public:
            template<typename C, typename = std::enable_if_t<std::is_class<C>::value>>
            MyClass(C) { }
        
            template<typename C>
            MyClass(C*) { }
        };
        

        并非所有这些都需要由std::enable_if_t完成。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-08-13
          • 1970-01-01
          • 2017-09-27
          • 1970-01-01
          • 2013-01-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多