【发布时间】:2017-01-13 19:45:50
【问题描述】:
部分 C++11 代码从 Clang 到 g++ 的移植
template<class T>
using value_t = typename T::value_type;
template<class>
struct S
{
using value_type = int;
static value_type const C = 0;
};
template<class T>
value_t<S<T>> // gcc error, typename S<T>::value_type does work
const S<T>::C;
int main()
{
static_assert(S<int>::C == 0, "");
}
为 Clang(版本 3.1 到 SVN 主干)与任何 g++ 版本提供不同的行为。对于后者,我收到错误like this
prog.cc:13:13: error: conflicting declaration 'value_t<S<T> > S< <template-parameter-1-1> >::C' const S<T>::C; ^ prog.cc:8:29: note: previous declaration as 'const value_type S< <template-parameter-1-1> >::C' static value_type const C = 0; ^ prog.cc:13:13: error: declaration of 'const value_type S< <template-parameter-1-1> >::C' outside of class is not definition [-fpermissive] const S<T>::C;
如果我使用完整的typename S<T>::value_type 而不是模板别名value_t<S<T>>,那么g++ also works。
问题:模板别名不应该与其底层表达式完全互换吗?这是一个 g++ 错误吗?
更新:Visual C++ 也接受类外定义中的别名模板。
【问题讨论】:
-
当然看起来它们应该是等价的:eel.is/c++draft/temp.alias#2
-
我将使用 500 的编译器错误,Alex
-
我不认为这是微不足道的。关于别名模板的依赖类型等价存在很多问题。请参阅open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1979 以及与之相关的所有问题。答案应该涵盖这个问题以及这些问题在这个问题上的相关性,IMO。
-
它并不止于此。关于
typename S<T>::value_type案例是否有效,还有一个由来已久的问题,您还可以写什么:open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2。 -
我认为在编译器中,别名模板在 14.5.6.1p5 的“等效”检查完成之前被替换。所以
value_t<foobar>应该等价于foobar::value_type,即使涉及依赖类型。这也是 Barry 引用的段落所说的(它使用“等效”,尽管没有对 14.5.6.1p5 的脚注,这可以澄清它的意思是指“等效”的含义)。
标签: c++ c++11 templates g++ template-aliases