首页 文章

使用来自元函数的typedef声明成员函数

提问于
浏览
7

请考虑以下代码:

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 回答

  • 4

    [temp.spec]/8

    如果函数声明通过依赖类型获取其函数类型而不使用函数声明符的语法形式,则程序格式错误 .

    这使你的最后一行显然格格不入 . 这是有道理的,因为在其他依赖构造的情况下,我们不希望短语的含义过于依赖模板参数 .

    但是,[dcl.fct]/13

    函数类型的typedef可用于声明函数,但不能用于定义函数 .

    这使你的前三行格式正确 - 前两行直接,第三行,请注意

    当template-id引用别名模板的特化时,它等效于通过替换别名模板的type-id中的template-parameters的template-arguments获得的关联类型 .

    by [temp.alias] .

相关问题