MSVC2015中SFINAE成员检测输出错误
Wrong output for SFINAE member detect in MSVC2015
我正在学习SFINAE以及如何使用void_t
轻松实现它。但我得到不同的输出不同的编译器:
//pre c++17 void_t definition:
template<class... Ts> struct make_void {typedef void type;};
template<class... Ts> using void_t = typename make_void<Ts...>::type;
//check for member helper structures
template<class, class = void>
struct has_abc : std::false_type
{ };
template<class T>
struct has_abc<T, void_t<decltype(T::abc)>> : std::true_type
{ };
class has
{
public:
void abc();
};
class has_not
{ };
int main()
{
std::cout << has_abc<has>::value << std::endl;
std::cout << has_abc<has_not>::value << std::endl;
}
GCC 5.3.0打印预期输出1 0
,但MSVC 2015打印0 0
,为什么?
编辑:
另一个GCC 5.3.0代码违反c++语法的例子:
template<class T>
void test()
{
std::cout << std::is_same<decltype(T::func), void(T::*)(void)>::value << std::endl;
}
class Test
{
public:
void func();
};
int main()
{
test<Test>();
}
输出:1
实际上你的代码有一个错误。MSVC是正确的,而GCC是完全错误的。
指向成员函数的指针的语法不是这样的。有将&
放在表达式前面:
//check for member helper structures
template<class, class = void>
struct has_abc : std::false_type {};
template<class T>
struct has_abc<T, void_t<decltype(&T::abc)>> : std::true_type {};
// Notice the '&' there ------^
T::member
的语法只适用于静态数据成员,而typename T::member
适用于成员类型。在使用sfinae时,重要的是要区分小的语法属性和差异。
作为评论中的请求,这里有多个语句,显示非静态成员不能在没有&
的情况下被GCC 5.3引用:https://godbolt.org/g/SwmtG2
下面是一个GCC的例子:http://coliru.stacked-crooked.com/a/0ee57c2c34b32753
下面是MSVC的一个例子:http://rextester.com/FJH22266
c++标准中有一节明确指出,没有&
,表达式就不是很好地形成的:
[expr.prim。id]/2
表示类的非静态数据成员或非静态成员函数的id表达式只能使用:
作为类成员访问([expr.ref])的一部分,其中对象表达式引用成员的类或从该类派生的类,
或形成指向成员([expr.unary.op])的指针,或
如果id-expression表示非静态数据成员并且出现在未求值的操作数中。(例子:
struct S { int m; }; int i = sizeof(S::m); // OK int j = sizeof(S::m + 42); // OK
- end示例]
正如我们在聊天中讨论的那样,我们得出结论,这两个编译器之间存在差异的原因是GCC和MSVC都有bug,这些bug会阻止代码很好地工作。如前所述,如果有不相关的类没有正确实现规则,MSVC将拒绝应用SFINAE规则:http://rextester.com/FGLF68000
请注意,有时,更改类型trait的名称有助于MSVC正确解析我的代码,但它大多是不可靠的。
如果你想让你的代码像预期的那样工作,考虑向微软报告一个bug并升级你的GCC版本。
这样做:
template<class T>
struct has_abc<T, void_t<decltype(std::declval<T>().abc())>> : std::true_type
{ };
- 输出错误,问题是找到总和5000位数字cpp
- 使用复制构造函数的程序输出错误
- 异或字符串加密/解密输出错误
- 在linux上使用g++输出错误,在windows上更正
- 使用递归函数 (c++) 将长字符串转换为整数时输出错误
- ECDSA 密钥对生成输出错误
- fscanf() 输出错误的值
- 输入 1024 后十进制到二进制转换的输出错误?
- 输出错误命令的条件语句
- cuSparse (cusparseDcsrgemm) 中的矩阵乘法输出错误的结果
- 为什么 du -sh 输出错误大小的内存映射文件
- VS2017 的输出错误,但 mingw 有效
- 如何使FFMPEG C 代码不输出错误消息
- 乘以时输出错误.这是我编译器中的错误吗?C
- 输出错误:两个不同编译器上的不同输出:Prime Cryptarithm USACO
- 为什么输出错误崩溃
- C++输入/输出错误
- 尝试用 c++ 制作一个简单的加法器.编译成功,但输出错误
- 当我使用此合并排序代码运行时,输出错误
- 递归功能输出错误的值