好的,假设我想检查模板参数是否有嵌套类型/typedef XYZ。
template <class T>
struct hasXZY
{
typedef char no;
typedef struct { char x[2]; } yes;
template <class U>
static yes f(typename U::XYZ*);
template <class /*U*/>
static no f(...);
enum {value = sizeof(f<T>(0))==sizeof(yes)};
};
工作正常,符合预期。
现在考虑一下:
template <class T>
struct hasXZY
{
typedef char no;
typedef struct { char x[2]; } yes;
static yes f(typename T::XYZ*);
static no f(...);
enum {value = sizeof(f(0))==sizeof(yes)};
};
hasXYZ<int>
现在会导致编译时错误。好的,f 不是模板函数。但另一方面,当hasXYZ
通过 hasXYZ<int>::value
为 int 实例化, 编译器可以很容易地排除 f(int::XYZ*)
从候选人名单。我只是不明白为什么类模板中成员函数声明的实例化失败一定会导致整个类实例化失败。有什么想法吗?
编辑: 我的问题是:为什么成员函数声明应该全部格式正确?由于编译器仅在使用时实例化这些方法,为什么它需要正确的声明。将上面的示例 2 视为此功能的可能用例。
最佳答案
SFINAE 仅在为函数重载决策创建候选集时使用。在您的第一个示例中,您正在调用重载的 f() 函数,由于 SFINAE,第一个被排除在外。
在你的第二个例子中,当实例化 hasXZY 时,它的所有成员都必须定义良好,并且模板参数的替换不能失败。它适用于 int::XYZ。
成员不会因为替换失败而被排除在类(class)之外。
关于c++ - 为什么类模板的成员函数声明都应该是良构的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4000288/