const 对象作为数据成员与普通变量

Ash*_*wal 8 c++

我试图创建一个类,该类将使用将通过模板传递的Container类的对象。Comparator

所以我正在做类似的事情:

template<typename T>
class Container{
    const T c;
};


struct Comparator{
    public:
    bool operator()(const int a, const int b)const{
        return a < b;
    }
};

int main(){
    Container<Comparator> container;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我尝试编译此代码时,出现以下错误:

e.cpp:28:27: error: uninitialized const member in 'class Container<Comparator>'
   28 |     Container<Comparator> container;
      |                           ^~~~~~~~~
e.cpp:16:13: note: 'const Comparator Container<Comparator>::c' should be initialized
   16 |     const T c;
      |      
Run Code Online (Sandbox Code Playgroud)

为了摆脱这个错误,我所做的只是在Comparator类中添加了一个默认构造函数:

struct Comparator{
    public:
    Comparator(){
        
    }
    bool operator()(const int a, const int b)const{
        return a < b;
    }
};
Run Code Online (Sandbox Code Playgroud)

但我观察到的奇怪的事情是,当我将类的 const 对象Comparator作为普通变量(而不是任何类的数据成员)时,我没有收到任何类型的错误。

struct Comparator{
    public:
    bool operator()(const int a, const int b)const{
        return a < b;
    }
};

int main(){
    const Comparator comp;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Comparator所以我的问题是为什么在类中创建该类型的 const 对象时会出现错误,而不是在创建相同类型的普通 const 对象时会出现错误?

use*_*522 5

如果没有为变量指定初始值设定项,const Comparator则它必须是const-default-constructible。但是您的类Comparator是 const-default-constructible,因为它没有非静态数据成员。有关确定的实际规则,请参阅[dlc.init.general]/7

这不仅是对此类变量的要求,而且还要求如果类具有不带初始值设定项的类似非静态成员,则不会导致隐式默认构造函数被删除,请参阅[class.default.ctor]/2.4

所以你的原始代码应该可以编译。MSVC 会编译它,但 GCC 和 Clang 不会。

然而,针对类别成员的相关要求已更改为缺陷报告中引用的措辞:CWG 2394。在此之前,它要求成员具有用户提供的默认构造函数,这是比 const-default-constructible 更严格的要求,并且这正是您为使其工作而添加的内容。

根据Clang 实现状态页面GCC 实现状态页面,它们的 DR 实现状态未知。