#include <type_traits>
template<bool b>
struct S
{
template<typename = std::enable_if_t<b>>
S() {}
template<typename = std::enable_if_t<!b>>
S(int) {}
};
S<true> s{}; // error in clang/gcc, OK in VC2017
S<false> s{0}; // error in clang/gcc, OK in VC2017在这两种情况下,clang/gcc都试图实例化由于SFINAE而应该丢弃的ctor。错误信息是:
错误:在'std::enable_if< false,void>‘中没有一个名为“enable_if”的类型不能用于禁用此声明
clang/gcc对另一个ctor的实例化是不正确的,因为它应该而不是在可能的重载列表中,对吗?
但是在我提交一个bug之前,我想看看其他人的想法。也许我搞错了.
发布于 2017-10-06 10:50:56
这是MSVC中的一个bug,clang和gcc是对的。
问题是SFINAE只发生在过载分解过程中,而不是以前。我的意思是,如果这个函数在你调用它之前是不正确的,那就是一个错误。
例如,当您使用S<true>时,将实例化整个类。它看起来有点像这样:
struct S_true
{
template<typename = void>
S() {}
template<typename = /*fail*/>
S(int) {}
};正如您所看到的,第二个构造函数的格式完全错误,它不是一个有效的定义,因为没有找到类型type (因为std::enable_if)。因此,SFINAE甚至不能发挥作用,类定义是错误的和诊断的。
您需要将模板参数b作为两个构造函数的模板参数列表的一部分(请查看@bolov的答案)。
发布于 2017-10-06 11:41:24
@ right 1111是100%正确的。
您需要将模板参数bool作为两个构造函数的模板参数列表的一部分。
下面是如何做到这一点(这是一种非常标准的技术):
template<bool b>
struct S
{
template<bool bb = b, typename = std::enable_if_t<bb>>
S() {}
template<bool bb = b, typename = std::enable_if_t<!bb>>
S(int) {}
};https://stackoverflow.com/questions/46603353
复制相似问题