Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 deleted/defaulted constructors

I'm a bit confused about how/why the constructors are called in C++11 and C++17.

#include <iostream>
using namespace std;

//---

template<typename T>
struct StructTest
{
public:
  const T Var = -1;

  //---

  // constexpr StructTest() = delete;  // 1
  // constexpr StructTest() = default; // 2

  // constexpr StructTest(const StructTest &Source) = delete;                  // 3
  // constexpr StructTest(const StructTest &Source) = default;                 // 4
  // constexpr StructTest(const StructTest &Source) {cout << "Copy" << endl;}; // 5
};

//---

StructTest<int> A{};
StructTest<int> A1{1};
StructTest<int> A2(A);

//---

int main(void)
{
  return(0);
};

So I'm confused by what happens when I uncomment some combination of lines (and compiling with the c++17 standard flag with clang):

  • 1, Compiles. List init's for A and A1, and the default copy constructor for A2
  • 2, Compiles. Default constructor for A and list init A1(?), and the default copy constructor for A2
  • 1 + 3 or 2 + 3, Fails to compile because of the deleted copy constructor for A2
  • 1 + 4, Compiles. Default constructor for A and list init A1(?), and the default copy constructor for A2
  • 2 + 4, Compiles. Default constructor for A and list init A1(?), and the default copy constructor for A2
  • 1 + 5, Fails to compile. Says A is missing(deleted) a default constructor, and no matching constructor for A1?
  • 2 + 5, Fails to compile. No matching constructor for A1?

I think I understand most of this, but I'm confused why the 1 + 5, and 2 + 5 compiles fail. Could anyone explain the logic the compiler is using to select the constructors that it's going to use, and why it fails to compile?

If the constructors that I think are being called in the other cases are wrong, could you also point out what is being called, and why?

like image 368
Andy Avatar asked Dec 02 '22 10:12

Andy


1 Answers

1, Compiles. List init's for A and A1, and the default copy constructor for A2

What you call List init in this case is actually aggregate initialization because StructTest is an aggregate. This is allowed because the presence of an explicitly defaulted or deleted constructor still makes the class an aggregate.

2, Compiles. Default constructor for A and list init A1?, and the default copy constructor for A2

A1 is aggregate initialized like what happened in 1. The rest it correct

1 + 3 or 2 + 3, Fails to compile because of the deleted copy constructor for A2

This is the expected behavior since the copy constructor is marked as deleted.

1 + 4, Compiles. Default constructor for A and list init A1?, and the default copy constructor for A2

Again, aggregate initialization for A and A1

2 + 4, Compiles. Default constructor for A and list init A1?, and the default copy constructor for A2

A and A1 will be aggregate initialized but it will use the default member initializer of Var when initializing A per [dcl.init.aggr]/5.1

1 + 5, Fails to compile. Says A is missing(deleted) a default constructor, and no matching constructor for A1?

5 is a user provided non defaulted or deleted constructor. This means StructTest is no longer an aggregate and you cannot aggregate initialize it anymore.

2 + 5, Fails to compile. No matching constructor for A1?

Same reason as 1 + 5

like image 82
NathanOliver Avatar answered Dec 04 '22 01:12

NathanOliver