【问题标题】:template aliases and sfinae模板别名和 sfinae
【发布时间】:2012-12-06 03:26:15
【问题描述】:

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

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

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

谢谢:-)

【问题讨论】:

  • clang -v 说什么? Clang 3.3 trunk 编译代码就好了。
  • Debian clang 3.1-8 版本在这里,看来我只需要等待。感谢您的反馈!
  • 你能不能去掉模板别名,只是为了简化一点
  • @Dave:问题的重点在于使用别名,所以...
  • @Xeo 哦,对不起。我只看了代码,还以为是关于 SFINAE 的。

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


【解决方案1】:

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

但目前存在一个问题,请参阅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

【讨论】:

  • “根据会议结果,似乎需要 clangs 行为”——这不会完全杀死任何EnableIf 别名吗? 似乎非常不希望有别名模板不生成 SFINAE 软错误。
  • @Xeo 是的,那会很糟糕。事实上,clang trunk 接受 EnableIf 别名,所以在我看来,提问者观察到的行为只是一个 clang 错误,而且 wg21 网站上的问题摘要只是令人困惑(恕我直言)。
  • 是的,我很困惑,因为我已经评论说主干编译代码很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
  • 1970-01-01
  • 2017-01-20
  • 2019-01-15
  • 1970-01-01
相关资源
最近更新 更多