C++ deleted constructors
Asked Answered
E

2

6

Say I have this structure:

struct F
{
    int& ref; // reference member
    const int c; // const member
    // F::F() is implicitly defined as deleted
};

That is from cppreference. As I understand from the documentation the constructor of F is considered deleted because it has a reference variable which refers to nothing. So one cannot declare a variable of type F like so: F variableName; as there will be errors such as: uninitialized reference member in struct F.

I understand this however I do not understand what such a structure would be good for if you cannot even declare a variable of its type. Could such a data type be useful in some specific case?

Erine answered 1/5, 2018 at 7:42 Comment(0)
C
9

Since F is an aggregate you can use aggregate initialization:

int a = 42;
F f1 = {a, 13};

// or

F f2{a, 9};

Live demo.

A class type (typically, struct or union) is an aggregate if it has:

  • no private or protected non-static data members
  • no user-provided, inherited, or explicit (since C++17) constructors (explicitly defaulted or deleted constructors are allowed) (since C++11)
  • no virtual, private, or protected (since C++17) base classes
  • no virtual member functions
Cupellation answered 1/5, 2018 at 7:53 Comment(1)
I'd copy over the relevant details, specifically why is the data type in the example an aggregate.Lunik
D
6

I understand this however I do not understand what such structure would be good for if you cannot even declare a variable of it's type. Could such a data type be useful in some specific case?

The implicitly defaulted constructor being deleted doesn't mean you can't use this type ever. It means you must define the constructor yourself, because only you, the programmer, can know what that reference should be bound to. So the compiler is leaving it up to you, and if you forget, you'll be notified the c'tor is deleted.

That's why it's deleted, but as folks mentioned, that in itself doesn't mean you can't use that structure as is. It's still possible to aggregate initialize it (won't be possible if it had private data members however, so there's that to consider too).

A simple use case may be to alias members. For instance (this is kind of a toy example, you can use default member initializers instead):

struct Point {
  double coord[3];
  double& x;
  double& y;
  double& z;

  Point() : x(coord[0]), y(coord[1]), z(coord[2]) {}
};

Reference members also mean you would need to provide definitions for other member function to ensure your objects operate correctly, since they complicate matters somewhat. This is why they are usually avoided.

Other uses cannot really be enumerated exhaustively.

Denby answered 1/5, 2018 at 7:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.