Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a non-aggregate class with deleted constructors and destructor be ever instantiated?

Consider the following class:

template <class T>
class object {
public:
    using type = T;

    object() = delete;
    object(const object&) = delete;
    object(object&&) = delete;
    object& operator=(const object&) = delete;
    object& operator=(object&&) = delete;
    ~object() = delete;

private:
    type value = 0;
};

Is it possible to instantiate an object (on the stack (probably not) or on the heap (maybe?)) of type object<int> by any weird trickery, or is it impossible for an object<int> to ever exist in any conceivable (well formed and with well defined behavior) C++17 program?

Addendum: First we consider non ill-formed NDR programs/non undefined behavior. If and only if, there are only ill-formed NDR programs/undefined behavior programs possible, you can illustrate the answer with such a program.

like image 595
Vincent Avatar asked Apr 11 '18 11:04

Vincent


2 Answers

No it cannot. From [basic.life]

[...] The lifetime of an object of type T begins when:

  • storage with the proper alignment and size for type T is obtained, and

  • if the object has non-vacuous initialization, its initialization is complete,

Thus initialization must be performed. We then look at all the possible initializations.

  1. If the initializer is {...}, then it is list-initialized.

    • The class is non-aggregate, so it cannot be aggregate-initialized.
    • The class has no default constructor, so it can't be value-initialized by {}
    • The class can be direct-initialized or copy-initialized by a {x}, which calls a constructor through overload resolution
  2. If the initializer is (), then it is value-initialized

  3. If the initializer is the same cv-unqualified type, the initializer expression for the initializer is used instead as the initializer

    • That is, T x = T(T()); is just to default-initialize x, with no copies
  4. If there is no initializers, then it is default-initialized

  5. Otherwise constructors are considered and called with overload resolution.

  6. To value-initialize is to default-initialize the object in this case.

  7. Default-initialization calls the default constructor in this case.

If you look carefully, there is only one way on this list to initialize the object, and that is to call a constructor. Since we have deleted all constructors, we can't initialize the object.

like image 200
Passer By Avatar answered Nov 15 '22 18:11

Passer By


I don't claim this to be an answer (am not a language lawyer), just post some findings from n4659:

11.6.20: An object whose initialization has completed is deemed to be constructed, even if no constructor of the object’s class is invoked for the initialization. [ Note: Such an object might have been value-initialized or initialized by aggregate initialization (11.6.1) or by an inherited constructor (15.6.3). —end note ]

From the 3 options mentioned in the note, only the first applies:

11.6.8: To value-initialize an object of type T means ... (8.1) — if T is a (possibly cv-qualified) class type (Clause 12) with either no default constructor (15.1) or a default constructor that is user-provided or deleted, then the object is default-initialized;

Since a default constructor is deleted:

11.6.7: To default-initialize an object of type T means ... (7.1) — If T is a (possibly cv-qualified) class type (Clause 12), constructors are considered. The applicable constructors are enumerated (16.3.1.3), and the best one for the initializer () is chosen through overload resolution (16.3). The constructor thus selected is called, with an empty argument list, to initialize the object.

Since there is no constructor that can be called, I think the instance of class object cannot be constructed.

like image 44
Daniel Langr Avatar answered Nov 15 '22 20:11

Daniel Langr