Declaring a member function with a typedef coming from a metafunction

ぐ巨炮叔叔 提交于 2020-01-21 04:45:18

问题


Consider the following code:

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

The declaration of foo4 fails on GCC 7.2, Clang 5.0.0 and 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

All of them seem to think that I am trying to declare a data member with a function type. As you can see, this only happens when the type is nested (not a using template), and is dependent on the parameter of the class. This looks like a bug, but the fact that for once all of these three compilers agree has me doubting.

Is this standard behaviour? If so, is there a rationale behind disallowing this, and is there a way to declare a member function whose type is computed with a metaprogram?


回答1:


[temp.spec]/8:

If a function declaration acquired its function type through a dependent type without using the syntactic form of a function declarator, the program is ill-formed.

This makes your last line decidedly ill-formed. Which makes sense, since, as in other cases of dependent constructs, we don't want the meaning of a phrase to depend too strongly on template arguments.

However, [dcl.fct]/13:

A typedef of function type may be used to declare a function but shall not be used to define a function.

This makes your first three lines well-formed---the first two directly, and for the third one, note that

When a template-id refers to the specialization of an alias template, it is equivalent to the associated type obtained by substitution of its template-arguments for the template-parameters in the type-id of the alias template.

by [temp.alias].



来源:https://stackoverflow.com/questions/47473986/declaring-a-member-function-with-a-typedef-coming-from-a-metafunction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!