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

non-static data member initialization with new expression

本文关键字:静态 数据成员 初始化 new 表达式      更新时间:2023-10-16

考虑以下代码:

#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),但我想我要问一下:上面的例子是否有任何原因不应该编译?

编译错误:

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    
           ^

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

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

Clang已经实现了一段时间的解决方案(可能暂时解析表达式,如果失败则重新尝试),Nathan Sidwell刚刚取消了相关的g++错误并将其分配给自己,所以我希望他计划尽快修复它。

有趣,我觉得应该可以。

这个可以编译:

#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