在模板参数中通过SFINAE选择构造函数

Den*_*ank 3 c++ templates sfinae c++14

我正在尝试通过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) { }
};
Run Code Online (Sandbox Code Playgroud)

但编译器抱怨以下错误:

错误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) { }
};
Run Code Online (Sandbox Code Playgroud)

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

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

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

// Shall raise an error
// MyClass<int> mc2(0);
Run Code Online (Sandbox Code Playgroud)

性状std::is_pointerstd::is_class只是一个例子,原来的特点是更加复杂.

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

Yak*_*ont 8

问题是参数的默认值不是模板方法签名的一部分.所以你有两个template<class C,class>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) { }
};
Run Code Online (Sandbox Code Playgroud)

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