关于const-default-constructible对象是否可为非类类型的C++标准条款疑问
First, let's clear up your core misunderstanding: const-default-constructible is not limited to class types—your initial assumption that it only applies to classes, structs, or unions is incorrect. The standard uses this concept for all types, with [dcl.init]/7 spelling out specific rules for class types, while non-class types follow their own constraints for default initialization of const-qualified instances.
Breaking down the definitions
Let’s start with the fundamental meaning:
A type T is const-default-constructible if and only if a const T object can be default-initialized without producing ill-formed code.
For non-class types
For non-class, non-array types (like int, char, or pointers), a const-qualified instance cannot be default-initialized. The standard mandates that such objects must be explicitly initialized. For example:
const int a; // Ill-formed: const non-class objects require explicit initialization
This means non-class types like int are not const-default-constructible, which aligns with your initial intuition about const int.
For class types
[dcl.init]/7 outlines the conditions for a class type T to be const-default-constructible:
- Either its default initialization invokes a user-provided constructor (not inherited from a base class), OR
- Every direct non-variant non-static data member has a default member initializer.
These rules ensure a const class instance can be safely default-initialized.
Resolving the "contradiction" in [class.default.ctor]/2
The clause [class.default.ctor]/2 states that a class's defaulted default constructor is deleted if:
Any non-variant non-static data member of const-qualified type (or array thereof) with no brace-or-equal-initializer is not const-default-constructible.
This does not conflict with [dcl.init]/7. Here’s why:
- The word "any" includes non-class types because those types fail the const-default-constructible check (as we saw,
const intcan’t be default-initialized without an explicit initializer). - The clause simply enforces that if you have a const member (class or non-class) without an initializer, that member’s type must support default initialization of its const form—otherwise, the default constructor can’t be valid.
Analyzing your examples
Example 1
struct S { const int I; // S::I's type (const int) is NOT const-default-constructible S() = default; };
Since const int is not const-default-constructible and I has no brace-or-equal initializer, the defaulted constructor for S is deleted—this directly follows [class.default.ctor]/2.
Example 2
struct X { const int M = 0; // X::M has a default member initializer X() = default; };
Here, the default member initializer (=0) bypasses the need for const int to be const-default-constructible. The default constructor will initialize M using the provided value, so it is well-formed and not deleted. [class.default.ctor]/2 only applies to members without brace-or-equal initializers—this example does not trigger that condition.
Is there a standard wording gap?
No, the wording is consistent once you recognize that const-default-constructible is a general type property, not just a class-specific one. [dcl.init]/7 focuses on class types because their rules are more complex, but the concept applies to all types as needed in other clauses like [class.default.ctor]/2.
内容的提问来源于stack exchange,提问作者mada

