Original post edited to provide more minimal reproduction.
Long-time C programmer here, relearning C++ for first time since about 2010, so I'm quite new to all the modern C++11 and beyond stuff. I think I understand the intent behind copy and move constructors and why one would explicitly define/default/delete them. However, I'm pretty lost on the interactions between the different constructor types in my own practice program:
TerritoryUSA.hpp
#ifndef TERRITORYUSA_HPP
#define TERRITORYUSA_HPP
namespace TerritoryUSA {
enum class Identifier {
Alabama,
Alaska,
American_Samoa
};
class Territory {
private:
Identifier identifier;
public:
// Construct.
Territory(Identifier identifier);
//Territory(Territory& other) = delete; // 1
//Territory(Territory&& other) = delete; // 2
// Move.
//Territory& operator=(Territory& other) = delete; // 3
//Territory& operator=(Territory&& other) = delete; // 4
// Destruct.
~Territory() = default;
// Methods.
Identifier getIdentifier();
};
}
#endif /* TERRITORYUSA_HPP */
TerritoryUSA.cpp
#include "TerritoryUSA.hpp"
using namespace TerritoryUSA;
// Construct.
Territory::Territory(Identifier identifier) : identifier{identifier} {}
// Methods.
Identifier Territory::getIdentifier() {
return identifier;
}
main.cpp
#include <cstdio>
#include "TerritoryUSA.hpp"
using namespace TerritoryUSA;
int main() {
Territory territories[]{
Territory(Identifier::Alabama),
Territory(Identifier::Alaska),
Territory(Identifier::American_Samoa)
};
for (Territory territory : territories) {
printf("%d\n", static_cast<int>(territory.getIdentifier()));
}
}
output
0
1
2
Program ended with exit code: 0
Note that this is done in Xcode on MacOS, which I'm also in the throes of figuring out as I mostly work with vim/make on Linux when writing C. I have't figured out where to find the compiler version yet, but this is a brand new updated Macbook with freshly installed Xcode, so it can't be very old. All I did was start a new Xcode "command line tool" application and put the 3 files in the project directory using the right click menu, so the build system should be correct (and it does build and run successfully when the marked lines are commented).
The part that's confusing the heck out of me is when I selectively uncomment the lines marked 1-4 in the header file, I get varying errors related to the construction of Territory objects. Here are the results I get when uncommenting single lines:
Line 1:
Lines 8-10 of main.cpp (where I try to instantiate the Territory objects) I get this red error:
No matching constructor for initialization of 'TerritoryUSA::Territory'
It also highlights in gray line 17 of the hpp (the constructor that takes an identifier argument) with this message:
1. Candidate constructor not viable: no known conversion from 'TerritoryUSA::Territory' to 'TerritoryUSA::Identifier' for 1st argument
It also highlights the uncommented Line 1 in gray with this message:
2. Candidate constructor not viable: expects an l-value for 1st argument
Line 2:
Lines 8-10 of main.cpp (where I try to instantiate the Territory objects) I get this red error:
Call to deleted constructor of 'TerritoryUSA::Territory'
It also highlights the uncommented Line 2 in gray with this message:
1. 'Territory' has been explicitly marked deleted here
Line 3:
No errors
Line 4:
Lines 8-10 of main.cpp (where I try to instantiate the Territory objects) I get this red error:
Call to implicitly-deleted copy constructor of 'TerritoryUSA::Territory'
It also highlights the uncommented Line 4 in gray with this message:
1. Copy constructor is implicitly deleted because 'Territory' has a user-declared move assignment operator
Questions
For Line 1, why is it trying to use a no-argument constructor and/or make any implicit assumptions? Haven't I provided a perfectly valid explicit constructor for the signature with 1 Identifier argument? I intentionally do not want to allow users to instantiate Territory objects without any arguments (quite frankly, I don't want them to instantiate them at all, but one step at a time). And also, what does deleting a copy constructor have to do with this? I'm not trying to copy anything.
For Line 2, again, I understand that I deleted the default constructor, but I'm not trying to use it, I'm trying to use the one that takes an identifier. Why am I getting tripped up? And also, what does deleting a move constructor have to do with this? I'm not trying to move anything.
For Line 4, why am I getting an error related to a deleted copy constructor if I'm deleting a move operator? I'm totally lost on this one, especially because Line 3 didn't have any errors.