宣布具有来自元功能的typedef的会员函数

Declaring a member function with a typedef coming from a metafunction

本文关键字:typedef 函数 功能 布具      更新时间:2023-10-16

考虑以下代码:

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;
                             ^~~~

clang:

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模板)时才发生,并且取决于类的参数。这看起来像是一个错误,但事实是,这三个编译器都同意一次都怀疑。

这是标准行为吗?如果是这样,是否有不称赞此内容的基本原理,是否有一种方法可以声明使用元图计算的类型?

[temp.spec]/8:

如果函数声明通过依赖类型获取了其函数类型,而无需使用函数声明器的句法形式,则该程序的形式不正确。

这使您的最后一行绝对不良。这是有道理的,因为与其他依赖结构一样,我们不希望短语的含义太强烈地依赖于模板参数。

但是,[dcl.fct]/13:

函数类型的打字机可用于声明功能,但应 不用于定义函数。

这使您的前三行形成良好---前两条直接的两行,对于第三条,请注意

当A template-id 是指别名模板的专业化 它等同于通过替换获得的相关类型 它的 template-argument 模板参数 type-id 中 别名模板。

作者[temp.alias]。