【问题标题】:Declaring a member function with a typedef coming from a metafunction使用来自元函数的 typedef 声明成员函数
【发布时间】:2020-05-03 23:13:25
【问题描述】:

考虑以下代码:

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 上失败。

海合会:

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

这是标准行为吗?如果是这样,是否有不允许这样做的理由,有没有办法声明一个其类型是用元程序计算的成员函数?

【问题讨论】:

  • 是的,这是标准的。见timsong-cpp.github.io/cppwp/temp#spec-8。不知道理由或为什么Foo_u&lt;T&gt; 被接受。
  • 可以定义这样的函数吗?例如,您如何定义foo3
  • @geza 您只能将其用于声明,定义需要通常的语法..
  • 这就是我问的原因,这个结构有什么用处?
  • @Rakete1111 所以这是一个“不,也许,不”......现在我很难过:(

标签: c++ language-lawyer c++17


【解决方案1】:

[temp.spec]/8:

如果函数声明通过依赖类型获取其函数类型,而不使用函数声明符的语法形式,则程序是非良构的。

这使您的最后一行明显不正确。这是有道理的,因为与其他依赖结构的情况一样,我们不希望短语的含义过于依赖模板参数。

但是,[dcl.fct]/13

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

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

template-id 指代别名模板的特化时, 它等效于通过替换获得的关联类型 它的 template-arguments 为 type-id 中的 template-parameters 别名模板。

[temp.alias].

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-16
    • 2017-12-17
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 1970-01-01
    相关资源
    最近更新 更多