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

标签 c++ templates c++14 sfinae

我正在尝试通过 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) { }
};

但是编译器报错如下:

error C2535: 'MyClass::MyClass(C)': member function already defined or declared

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

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

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);

traits std::is_pointerstd::is_class 只是一个例子,原来的traits更复杂。

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

最佳答案

问题是参数的默认值不是模板方法签名的一部分。所以你有两个 template<class C,class>ctor(c)相同的 Actor 。

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) { }
};

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

关于c++ - 在模板参数中通过 SFINAE 选择构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32167213/

相关文章:

c++ - 为什么在 C++ 中将字符串和字符连接起来会返回一个空字符串?

c++ - 编译模板时无限循环

c++ - 无法理解我的程序的输出

c++ - clang vs gcc - 空通用 lambda 可变参数包

c++ - 使用字符串引用

带有 char 和 wchar_t 的 C++ 正则表达式?

c++ - 使用 vector 迭代器不匹配 ‘operator=’

WPF ControlTemplate 部分替换

templates - 有没有办法使用 mixin 或模板从 D 中的类生成接口(interface)?

c++ - 类内部类型的静态私有(private)成员