12

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

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;
}

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

谢谢 :-)

4

1 回答 1

5

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

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

根据会议结果,似乎需要clangs行为:替换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

于 2012-12-05T19:26:15.257 回答