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

non-static data member initialization with new expression

考虑以下代码:

#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, but fails to compile on 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    
           ^

有趣,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

这是 Core issue 325 中描述的问题的另一个例子(参见 "Notes from the August, 2011 meeting" 中有一个非常相似的例子),即模板参数列表中的逗号在编译器尝试确定表达式的结尾位置。

这个问题仍然悬而未决,但委员会的共识是它应该起作用(尽管我不知道要改变什么才能使其有效)。

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