C++ SFINAE:有些失败比其他失败更平等?
我试图用它来区分一个类,它有一个名为“name”的成员。我在标准模式中设置了一些东西,但它不起作用——编译器不是默默地忽略“失败”的替换,而是生成一个错误 我确信我遇到了一些模板替换规则,如果有人能解释一下是哪一个,我将不胜感激 这是一个简单的例子。我正在使用gcc:C++ SFINAE:有些失败比其他失败更平等?,c++,templates,template-specialization,sfinae,C++,Templates,Template Specialization,Sfinae,我试图用它来区分一个类,它有一个名为“name”的成员。我在标准模式中设置了一些东西,但它不起作用——编译器不是默默地忽略“失败”的替换,而是生成一个错误 我确信我遇到了一些模板替换规则,如果有人能解释一下是哪一个,我将不胜感激 这是一个简单的例子。我正在使用gcc: template <typename U> string test( char(*)[sizeof(U::name)] = 0 ) { return "has name!"; } template <type
template <typename U> string test( char(*)[sizeof(U::name)] = 0 ) { return "has name!"; }
template <typename U> string test(...) { return "no name"; }
struct HasName { string name; }
struct NoName {}
cout << "HasName: " << test<HasName>(0) << endl; //fine
cout << "NoName: " << test<NoName>(0) << endl; //compiler errors:
//error: size of array has non-integral type `<type error>'
//error: `name' is not a member of `NoName'
模板字符串测试(char(*)[sizeof(U::name)]=0){return“has name!”;}
模板字符串测试(…){返回“无名称”;}
结构HasName{string name;}
结构非名称{}
cout以下内容似乎是有效的(尽管正如Michael所说,它不一定给出您在其他编译器上想要的结果):
gcc(gcc)4.3.4 20090804(发行版)1
也接受代码。下面是一个尝试:
// Tested on Microsoft (R) C/C++ Optimizing Compiler Version 15.00.30729.01
template<typename T>
class TypeHasName
{
private:
typedef char (&YesType)[2];
typedef char (&NoType)[1];
struct Base { int name; };
struct Derived : T, Base { Derived(); };
template<typename U, U> struct Dummy;
template<typename U>
static YesType Test(...);
template<typename U>
static NoType Test(Dummy<int Base::*, &U::name>*);
public:
enum { Value = (sizeof(Test<Derived>(0)) == sizeof(YesType)) };
};
#include <string>
#include <iostream>
struct HasName { std::string name; };
struct NoName {};
int main()
{
std::cout << "HasName: " << TypeHasName<HasName>::Value << std::endl;
std::cout << "NoName: " << TypeHasName<NoName>::Value << std::endl;
return 0;
}
//在Microsoft(R)C/C++优化编译器版本15.00.30729.01上测试
模板
类TypeHasName
{
私人:
typedef char(&YesType)[2];
typedef字符(&NoType)[1];
结构基{int name;};
派生结构:T,基{Derived();};
模板结构虚拟;
模板
静态叶氏试验(…);
模板
静态不定型试验(假人*);
公众:
枚举{Value=(sizeof(Test(0))==sizeof(YesType))};
};
#包括
#包括
结构HasName{std::string name;};
结构非名称{};
int main()
{
std::cout您使用的是哪种编译器?g++4.4.3接受此代码,即使使用-Wall-Wextra-pedantic
@Tyler:它甚至不会对结构定义之后缺少的分号发出诊断?;-)oops:-);我肯定会发出诊断(请原谅粗心的键入)一些额外的数据点:MSVC 9/10也接受代码(即使没有名称
成员上的静态
),但不会产生预期的输出。MinGW(GCC 3.4.5)在成员为静态
或不为静态
的情况下都不会编译它@Michael:那么也许我应该说“看起来很好”。我通常会“Comeau接受它”是“它是有效的C++”的同义词,但我认识到这只是一个非常好的近似值:-)哦,虽然Comeau接受代码,但它产生与MSVC相同的输出(也就是说,它对test()
的两个调用都说“没有名字”)@Michael:另外,我有一种模糊的感觉,C++0x中允许使用class::member
语法获取非静态数据成员的sizeof
。因此,如果编译器不使用static
,而接受它,@Steve g++不使用-std=C++98-pedantic
而接受它,也就不足为奇了。不确定g是否使用-std=C++98-pedantic++这里出了什么问题。
HasName: has name!
NoName: no name
// Tested on Microsoft (R) C/C++ Optimizing Compiler Version 15.00.30729.01
template<typename T>
class TypeHasName
{
private:
typedef char (&YesType)[2];
typedef char (&NoType)[1];
struct Base { int name; };
struct Derived : T, Base { Derived(); };
template<typename U, U> struct Dummy;
template<typename U>
static YesType Test(...);
template<typename U>
static NoType Test(Dummy<int Base::*, &U::name>*);
public:
enum { Value = (sizeof(Test<Derived>(0)) == sizeof(YesType)) };
};
#include <string>
#include <iostream>
struct HasName { std::string name; };
struct NoName {};
int main()
{
std::cout << "HasName: " << TypeHasName<HasName>::Value << std::endl;
std::cout << "NoName: " << TypeHasName<NoName>::Value << std::endl;
return 0;
}