Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

non-static data member initialization with new expression

Consider the following code:

#include <map>

template <typename T>
struct X {
    std::map<int, T>* storage = new std::map<int, T>();
};

int main() {
    X<int> x;
}

This compiles on clang 3.6.0, but fails to compile on gcc 5.1. It would compile, however, if the type of storage were instead std::vector<T>* (or just T*).

I'm fairly certain this is a compiler bug on gcc's part (edit: I submitted it as 66344), but thought I'd ask to make sure: is there any reason the above example shouldn't compile?

gcc compile error:

main.cpp:5:51: error: expected ';' at end of member declaration    
     std::map<int, T>* storage = new std::map<int, T>();    
                                                   ^    

main.cpp:5:51: error: declaration of 'std::map<int, T> X<T>::T'    
main.cpp:3:11: error:  shadows template parm 'class T'    
 template <typename T>    
           ^

main.cpp:5:52: error: expected unqualified-id before '>' token    
     std::map<int, T>* storage = new std::map<int, T>();    
                                                    ^    
main.cpp:5:46: error: wrong number of template arguments (1, should be at least 2)    
     std::map<int, T>* storage = new std::map<int, T>();    
                                              ^

In file included from /usr/local/include/c++/5.1.0/map:61:0,    
                 from main.cpp:1:    
/usr/local/include/c++/5.1.0/bits/stl_map.h:96:11: note: provided for 'template<class _Key, class _Tp, class _Compare, class _Alloc> class std::map'    
     class map    
           ^
like image 727
Barry Avatar asked May 30 '15 13:05

Barry


2 Answers

This is another example of the problem described in Core issue 325 (see the "Notes from the August, 2011 meeting" which have a very similar example), namely that the comma in the template argument list causes a parse failure when the compiler tries to determine where the end of the expression is.

The issue is still open, but the consensus of the committee is that it should be made to work (I don't know what will be changed to make it valid though).

Clang has implemented a workaround for some time (maybe tentatively parsing the expression and retrying if it fails) and Nathan Sidwell has just un-suspended the relevant G++ bug and assigned it to himself so I hope he plans to fix it soon.

like image 77
Jonathan Wakely Avatar answered Oct 24 '22 17:10

Jonathan Wakely


Interesting, it should work IMO.

This one does compile:

#include <map>

template <typename T>
struct X {
   typedef std::map<int, T> mt;
   mt *storage = new mt();
};

int main() {
        X<int> x;
}

Apparently something goes wrong with the template argument expansion...

Compile with:

g++ -o test test.cpp -std=c++11
like image 3
atlaste Avatar answered Oct 24 '22 15:10

atlaste