模板别名和sfinae

时间:2012-12-05 16:46:42

标签: c++ c++11 sfinae template-aliases

如果替换失败涉及模板别名(例如缺少的成员类型名称上的模板别名,如下面的代码片段中所示),是否应该触发错误?

Clang和gcc似乎对此持不同意见:

// some types
struct bar { };

struct foo {
    typedef void member_type;
};


// template alias
template<class T>
using member = typename T::member_type;


template<class T>
void baz(... ) { }

// only works for gcc, clang fails with: no type named 'member_type'
// in 'bar'
template<class T>
void baz( member<T>* ) { }


int main(int, char** ) {

    baz<bar>(0);            // picks first
    baz<foo>(0);            // picks second

    return 0;
}

所以问题是:谁是正确的,为什么?

谢谢: - )

1 个答案:

答案 0 :(得分:4)

根据标准,显然GCC是正确的,因为必须立即替换别名模板,然后在typename T::member_type已知时将正常/通常的SFINAE应用于T

但目前存在问题,请参阅http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1554

根据会议结果,似乎需要铿锵行为:T的替换将在别名模板的上下文中完成(即使在typename T::member_type中替换时,没有对别名模板的引用 - 它仍然需要被引用作为参数类型模式源自的源,如果这是它的实现方式)。


这类似于另一种可能影响实例化语义的定义时间丢失模式的情况

template<int I>
void f(int x[I]);

int main() {
  f<0>(nullptr);
}

在这种情况下,在我看来,标准规范性地明确该参数立即被int*替换,因此实例化起作用。见http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1322