Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用SFINAE对GCC和Clang给出了不同的结果_C++_Gcc_Clang_Sfinae - Fatal编程技术网

C++ 使用SFINAE对GCC和Clang给出了不同的结果

C++ 使用SFINAE对GCC和Clang给出了不同的结果,c++,gcc,clang,sfinae,C++,Gcc,Clang,Sfinae,我正在学习如何利用SFINAE发挥我的优势。我试图使用它根据对象中存在的serialize()函数来选择函数实现 这是我用来确定类型是否定义serialize()函数的代码: 模板 类HasSerialize{ 私人: typedef char yes[1]; typedef字符编号[2]; 模板静态yes&test(char[sizeof(&C::serialize)]; 模板静态无测试(…); 公众: 静态常量布尔值=sizeof(测试(0))==sizeof(是); }; 然而,它似乎给

我正在学习如何利用SFINAE发挥我的优势。我试图使用它根据对象中存在的
serialize()
函数来选择函数实现

这是我用来确定类型是否定义serialize()函数的代码:

模板
类HasSerialize{
私人:
typedef char yes[1];
typedef字符编号[2];
模板静态yes&test(char[sizeof(&C::serialize)];
模板静态无测试(…);
公众:
静态常量布尔值=sizeof(测试(0))==sizeof(是);
};
然而,它似乎给出了关于GCC和Clang的确切结果。假设以下代码:

模板
类NVPtypeSerializer{
公众:
模板
静态xmlChar*序列化(C值){
//serize()不可用
}
};
模板
结构NVPtypeSerializer{
公众:
模板
静态xmlChar*序列化(T值){
返回值;
}
};
这就是所谓的:

foo=NVPtypeSerializer::serialize(值);
其中类
Bar
没有
serialize()
函数。这段代码在Clang 3.1下编译得很好,但是在GCC 4.7.1上我得到以下错误:

error: ‘class Bar’ has no member named ‘serialize’
如果我将
struct-NVPtypeSerializer
更改为
struct-NVPtypeSerializer
,它可以在GCC上编译,但Clang会给出以下错误:

error: no member named 'serialize' in 'Bar'

问题在哪里?在我的密码里吗?我希望代码尽可能可移植。

这真的是代码
测试(char[sizeof(&C::serialize)])
?请注意,接受数组的函数的声明实际上声明了接受指针的函数:

template <typename C> static yes& test(char[sizeof(&C::serialize)]) ;
模板静态yes&test(char[sizeof(&C::serialize)];
这实际上意味着:

template <typename C> static yes& test( char* );
模板静态是&测试(char*);
顺便说一句,这就是使调用
test(0)
compile的原因。我认为这不是检测函数是否存在的正确方法。关于如何使用SFINAE检测类中是否存在成员/成员函数

(一个简单的解决方案是添加一个额外的默认参数——前提是您有一个启用C++11的编译器:

template <typename C, std::size_t = sizeof(&C::serialize)> 
static yes& test(int) ;
模板
静态是&测试(int);

)

这确实很令人惊讶,特别是考虑到名称
Bar
没有出现在任何地方。哦,对不起,我写了
NVPtypeSerializer
,但T是一个类型名,在编译时是Bar。我在原来的问题中更改了它。因此,我找到了编译错误的解决方案:
template struct type\u check;模板静态是和测试(类型检查)但是我仍然不明白为什么以前的解决方案会以如此奇怪的方式运行。我曾经去过那里,我已经做到了。。。但幸运的是,我不再热衷于极端的模板元编程,你现在可能真的无法理解在看到如此浪费脑力的同时有多么有趣(多么悲伤)。我希望你能尽快摆脱这种疾病,把你的时间花在一些能让你更加积极高效的事情上。不幸的是,我的经验表明,你有可能把我归类为C++抨击巨魔。有了很好的回答,我不明白为什么它会无效。即使它将衰减为
char*
&C::serialize
,仍需进行评估,因此这似乎是一种有效的SFINAE用法。也许GCC又来了?在任何情况下,+1作为您的解决方法--我不能等到VC++获得默认函数模板参数。@ildjarn:当编译器解析函数声明时,类型为t的N个元素的数组被转换为指向t的指针,因此重载根本没有提到
sizeof(&C::serialize)
。我可能错了,我从问题中得到了这个密码。MSalters建议使用此选项,因为它不依赖于特定于编译器的扩展名,如typeof,也不像decltype那样需要C++11。@David:我也不是肯定的,但我认为
char[0]
格式不正确,所以我认为它必须在分解为指针之前计算大小。@ildjarn:
void f(char[0])
在gcc和clang++(至少在我的旧版本:gcc4.5.3/clang++3.0)中都可以很好地编译,但是
void f(char[-1])
在这两种情况下都失败,所以可能是任何一种情况。