2014-08-27 70 views
3

标题引自此SO answer。它正在讨论使用SFINAE来检测具有给定签名的成员函数的存在,并在处理继承的成员函数时指出接受的答案中的方法失败。特别是,给出的解释如下模板实例化不会“继承”

如果你不是已经明白这个问题,那么看看头文件中std::shared_ptr<T>的定义就会显示出来。在那个实现中,std::shared_ptr<T>是从它继承的基类派生的operator*() const。因此,构成“找到”U = std::shared_ptr<T>的运算符的模板实例化SFINAE<U, &U::operator*>将不会发生,因为std::shared_ptr<T>本身没有operator*(),并且模板实例化不会“继承”。

使用“sizeof()技巧”,仅仅检测T是否具有某些成员函数mf(请参阅此答案和注释),这一障碍不会影响众所周知的SFINAE方法。

使用从答案的术语,是用什么作为T::mf模板参数来实例化一个类型VS编译器来确定它通过一个函数模板参数推导的区别? “模板实例化不会继承”是什么意思?最后,为什么不影响检查是否存在成员,如here

回答

3

最小化例如:

struct A { 
    void a() const; 
}; 

struct B : A {}; 

template<typename U, void (U::*)() const> struct SFINAE {}; 
template<typename U> void Test(SFINAE<U, &U::a>*) { } 

int main(void) 
{ 
    Test<B>(0); // doesn't compile 
    return 0; 
} 

Demo

的问题是,当B::aA继承的&B::a的类型实际上是“指针的A构件” - 和,而通常的指针到成员的碱基可以被隐式转换为指针 - 根据§14.3.2[temp.arg.nontype]/p5,此转换不适用于非类型模板参数:

对每个表达式执行以下转换用作 非类型模板参数。如果非类型的模板参数不能被转换为对应的模板参数 的类型,那么该程序是格式不正确的。类型的指针

  • [...]
  • 对于非型模板参数成员函数, 如果模板参数为std::nullptr_t型时, 空构件指针转换(4.11 ) 被申请;被应用;否则,不适用 转换。如果模板参数表示一组 重载成员函数,则匹配成员函数将从集合(13.4)中选择 。