# gcc -v Using built-in specs. COLLECT_GCC=/opt/bin/gcc Target: x86_64-pc-linux-gnu Configured with: ../gcc/configure --prefix=/opt/ --enable-languages=c,c++ Thread model: posix gcc version 9.0.0 20190118 (experimental) (GCC) # Description: When compiling the following code and uncommenting the first constructor of A it'll throw the error in the comment. The expected behaviour would either be "error: need 'typename' before 'T::type' because 'T' is a dependent scope" or no error at all. # Options: -O2 -std=c++2a -Wall -Wextra # Source Code: template<typename T> class A { public: using type = T::type; /*A(T::type a) : mA{a} {}*/ // error: expected ')' before 'a' A(type a); // OK constexpr void a(T::type a) noexcept { // OK mA = a; } [[nodiscard]] constexpr T::type a() const noexcept { // OK return mA; } private: T::type mA; // OK }; template<typename T> A<T>::A(T::type a) : mA{a} {} // OK struct B { using type = int; }; int main() { A<B> a{20}; a.a(10); return a.a(); }
I'll look though I'm not sure yet if there's an actual bug. Is there a version with 'typename's included that compiles?
I'm sorry if I'm misinterpreting this, but the program I wrote does compile with gcc 9.0, as the "error" part is commented out, so I'll just write what to do to get the descriped error: If my constructor is: A(typename T::type a) : mA{a} {} it is working, but if I remove the typename it'll give me The "error: expected ')' before 'a'" error. (As far as I know it should detect that it is only a missing typename, so for versions before c++20 it should be "error: need 'typename' [...]" and for c++20 it shouldn't be an error). So right now this won't compile: A(T::type a) : mA{a} {} But if I'd define the constructor out-of-line it won't give me an error: template<typename T> A<T>::A(T::type a) : mA{a} {} As GCC is detecting that there can only be a type at this position, which it doesn't with the "header-only"-version. I hope this will help.
Oh, so basically this should compile in C++2a: template<typename T> struct A { using type = T::type; A(type); }; template<typename T> A<T>::A(T::type a) {} but it doesn't. It does when I add 'typename' to the out-of-line ctor parameter.
And by the same token, I suspect this ought to work too: template<typename T> struct A { A(T::type); };
Author: mpolacek Date: Wed Mar 13 18:38:45 2019 New Revision: 269656 URL: https://gcc.gnu.org/viewcvs?rev=269656&root=gcc&view=rev Log: PR c++/88979 - further P0634 fix for constructors. * parser.c (cp_parser_decl_specifier_seq): Pass flags to cp_parser_constructor_declarator_p. (cp_parser_direct_declarator): Allow missing typename for constructor parameters. (cp_parser_constructor_declarator_p): Add FLAGS parameter. Pass it to cp_parser_type_specifier. * g++.dg/cpp2a/typename15.C: New test. Added: trunk/gcc/testsuite/g++.dg/cpp2a/typename15.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/parser.c trunk/gcc/testsuite/ChangeLog
Fixed.