参数列表中的void_t有效,但不作为返回类型

tem*_*boy 4 c++ templates c++11 c++14

关于使用别名的cppreference有一个例子.此示例失败,因为int没有成员foo:

template<typename...> using void_t = void;
template<typename T> void_t<typename T::foo> f();
f<int>(); // error, int does not have a nested type foo
Run Code Online (Sandbox Code Playgroud)

这很清楚,但是当我尝试将该void_t部件放入参数列表时,它意外地编译:

template<typename...> using void_t = void;
template<typename T> void f(void_t<typename T::foo>);
f<int>();
Run Code Online (Sandbox Code Playgroud)

它在clang上编译但在gcc中没编译.这是一个错误吗?

Yak*_*ont 8

template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;
Run Code Online (Sandbox Code Playgroud)

C++ 11标准中存在一个含糊不清的问题,即使用无效类型/表达式别名的模板的未使用模板参数是否是替换失败.

gcc和clang对这个条款的解释不同,这就是我认为你所看到的.以上void_t应该使它在gcc和clang中都一样.

  • 关于CWG1558相关问题,Clang通常是正确的,OP中的第二个片段也编译在GCC主干上,该主干应该也已经实现了CWG1558的分辨率.奇怪的事情发生在这里......可能与一个类型为`void`的参数有关. (2认同)
  • 有趣的 - N4140 [dcl.fct]/p4:"由非依赖类型`void`的单个未命名参数组成的参数列表相当于一个空参数列表." 当然,问题是`void_t <typename T :: foo>`是否依赖... (2认同)