使用新表达式初始化非静态数据成员

时间:2015-05-30 13:12:49

标签: c++ c++11 gcc language-lawyer

请考虑以下代码:

#include <map>

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

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

这会在clang 3.6.0上编译,但无法在gcc 5.1上编译。但是,如果storage的类型为std::vector<T>*(或仅T*),则会进行编译。

我相当肯定这是gcc上的编译器错误(编辑:我将其作为66344提交),但我想要确认:是否存在上述示例不应该编译?

的任何原因

gcc编译错误:

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    
           ^

2 个答案:

答案 0 :(得分:3)

有趣的是,它应该适用于IMO。

这个编译:

#include <map>

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

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

模板参数扩展显然出现了问题......

编译:

g++ -o test test.cpp -std=c++11

答案 1 :(得分:3)

这是Core issue 325中描述的问题的另一个例子(参见“2011年8月会议的注释”,其中有一个非常相似的例子),即模板参数列表中的逗号导致解析失败当编译器试图确定表达式的结尾位置时。

这个问题仍然存在,但委员会的共识是应该让它起作用(我不知道会改变什么以使其有效)。

Clang已经实施了一段时间的解决方法(可能暂时解析表达式并在失败时重试)并且Nathan Sidwell刚刚un-suspended the relevant G++ bug and assigned it to himself所以我希望他计划很快解决它。