请考虑以下代码:
template <class>
struct Foo_s {
using type = void();
};
template <class>
using Foo_u = void();
template <class T>
struct Bar {
Foo_u<void> foo1; // OK
typename Foo_s<void>::type foo2; // OK
Foo_u<T> foo3; // OK
typename Foo_s<T>::type foo4; // Boom.
};
template struct Bar<void>;
foo4
的声明在GCC 7.2,Clang 5.0.0和MSVC 19.10.25017上失败 .
GCC:
<source>: In instantiation of 'struct Bar<void>':
18 : <source>:18:17: required from here
15 : <source>:15:29: error: field 'Bar<void>::foo4' invalidly declared function type
typename Foo_s<T>::type foo4;
^~~~
铛:
15 : <source>:15:29: error: data member instantiated with function type 'typename Foo_s<void>::type' (aka 'void ()')
typename Foo_s<T>::type foo4;
^
18 : <source>:18:17: note: in instantiation of template class 'Bar<void>' requested here
template struct Bar<void>;
^
MSVC:
15 : <source>(15): error C2207: 'Bar<T>::foo4': a member of a class template cannot acquire a function type
18 : <source>(18): note: see reference to class template instantiation 'Bar<void>' being compiled
所有这些人似乎都认为我试图用函数类型声明一个数据成员 . 如您所见,这仅在类型嵌套(不是 using
模板)时发生,并且取决于类的参数 . 这看起来像一个错误,但事实上,这三个编译器都同意这一点让我怀疑 .
这是标准行为吗?如果是这样,是否有理由不允许这样做,有没有办法声明一个成员函数,其类型是用元程序计算的?
1 回答
[temp.spec]/8:
这使你的最后一行显然格格不入 . 这是有道理的,因为在其他依赖构造的情况下,我们不希望短语的含义过于依赖模板参数 .
但是,[dcl.fct]/13:
这使你的前三行格式正确 - 前两行直接,第三行,请注意
by [temp.alias] .