我正在尝试使用SFINAE来区分具有名为“name”的成员的类。我在似乎是标准模式的情况下进行设置,但它不起作用 - 而不是默默地忽略'失败'替换,编译器会产生错误。
我确信我遇到了一些模板替换规则,如果有人能解释哪一个,我将不胜感激。
这是一个精简的例子。我正在使用gcc:
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'
答案 0 :(得分:1)
以下内容似乎有效(尽管正如Michael所说,它并不一定能在其他编译器上提供您想要的结果):
#include <string>
#include <iostream>
using namespace std;
template <typename U> string test( char(*)[sizeof(U::name)] = 0 ) { return "has name!"; }
template <typename U> string test(...) { return "no name"; }
struct HasName { static string name; };
struct NoName { };
int main() {
cout << "HasName: " << test<HasName>(0) << endl;
cout << "NoName: " << test<NoName>(0) << endl;
}
输出:
HasName: has name!
NoName: no name
gcc(GCC)4.3.4 20090804(发布)1
Comeau也接受代码。
答案 1 :(得分:0)
以下是对此的尝试:
// 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;
}
我们的想法是,如果T
有一个名为name
的变量,那么Derived
将有两个name
个变量(一个来自T
,一个来自Base
{1}})。如果T
未声明name
变量,那么Derived
将只有一个来自Base
。
如果Derived
有两个name
个变量,则第二个&U::name
重载中的表达式Test()
将不明确,SFINAE应从重载集中删除该函数。< / p>