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
AandA1, and the default copy constructor forA2 - 2, Compiles. Default constructor for
Aand list initA1(?), 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
Aand list init A1(?), and the default copy constructor forA2 - 2 + 4, Compiles. Default constructor for
Aand list initA1(?), and the default copy constructor for A2 - 1 + 5, Fails to compile. Says
Ais missing(deleted) a default constructor, and no matching constructor forA1? - 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?
What you call List init in this case is actually aggregate initialization because
StructTestis an aggregate. This is allowed because the presence of an explicitly defaulted or deleted constructor still makes the class an aggregate.A1is aggregate initialized like what happened in 1. The rest it correctThis is the expected behavior since the copy constructor is marked as deleted.
Again, aggregate initialization for
AandA1AandA1will be aggregate initialized but it will use the default member initializer ofVarwhen initializingAper [dcl.init.aggr]/5.15 is a user provided non defaulted or deleted constructor. This means
StructTestis no longer an aggregate and you cannot aggregate initialize it anymore.Same reason as 1 + 5