I got a piece of code from the C++ Templates the Complete Guide book: In the following program, we create a Person class with perfect forwarded template constructor and two other member function (const copy constructor , move constructor)
#include <utility>
#include <string>
#include <iostream>
class Person
{
private:
std::string name;
public:
// generic constructor for passed initial name:
template<typename STR>
explicit Person(STR&& n) : name(std::forward<STR>(n)) {
std::cout << "TMPL-CONSTR for '" << name << "'\n";
}
// copy and move constructor:
Person (Person& p) : name(p.name) {
std::cout << "COPY-CONSTR Person '" << name << "'\n";
}
Person (Person const& p) : name(p.name) {
std::cout << "COPY-CONSTR Person '" << name << "'\n";
}
Person (Person&& p) : name(std::move(p.name)) {
std::cout << "MOVE-CONSTR Person '" << name << "'\n";
}
};
int main()
{
std::string s = "sname";
Person p1(s);
Person p2("tmp");
Person p3(p1); // Error
Person p4(std::move(p1));
}
Regarding the error at line Person p3(p1); Here the book says "According to overload resolution rules"
template<typename STR>
Person(STR&& n)
"is better match than the copy constructor"
Person(const Person& p)
So, if I add one more constructor inside Person as follows:
Person (Person& p) : name(p.name) {
std::cout << "COPY-CONSTR Person '" << name << "'\n";
}
The error should go away. Indeed the error went away and here is the output:
TMPL-CONSTR for 'sname'
TMPL-CONSTR for 'tmp'
COPY-CONSTR Person 'sname' : this is due to `Person (Person& p)`
MOVE-CONSTR Person 'sname'
But the book also says, this is a partial solution only, because template constructor of Derived class of Person is still a better match by the overload resolution rules.
So I tried to check that also:
#include <utility>
#include <string>
#include <iostream>
class Person
{
private:
std::string name;
public:
// generic constructor for passed initial name:
template<typename STR>
explicit Person(STR&& n) : name(std::forward<STR>(n)) {
std::cout << "TMPL-CONSTR for '" << name << "'\n";
}
// copy and move constructor:
Person (Person& p) : name(p.name) {
std::cout << "COPY-CONSTR Person '" << name << "'\n";
}
Person (Person const& p) : name(p.name) {
std::cout << "COPY-CONSTR Person '" << name << "'\n";
}
Person (Person&& p) : name(std::move(p.name)) {
std::cout << "MOVE-CONSTR Person '" << name << "'\n";
}
};
#if 1 // or 0
class newPerson : public Person
{
private:
std::string name;
public:
// generic constructor for passed initial name:
template<typename STR>
explicit newPerson(STR&& n) : name(std::forward<STR>(n)) {
std::cout << "TMPL-CONSTR for '" << name << "'\n";
}
// copy and move constructor:
newPerson (newPerson const& p) : name(p.name) {
std::cout << "COPY-CONSTR Person '" << name << "'\n";
}
newPerson (newPerson&& p) : name(std::move(p.name)) {
std::cout << "MOVE-CONSTR Person '" << name << "'\n";
}
};
#endif
int main()
{
std::string s = "sname";
Person p1(s);
Person p2("tmp");
Person p3(p1); // Error again
Person p4(std::move(p1));
}
I am pasting the clang error in this case (gcc error list were too big)
specialmemtmplMain.cpp:41:5: error: constructor for 'newPerson' must explicitly initialize the base class 'Person' which does not have a default constructor
newPerson (newPerson const& p) : name(p.name) {
^
specialmemtmplMain.cpp:5:7: note: 'Person' declared here
class Person
^
specialmemtmplMain.cpp:44:5: error: constructor for 'newPerson' must explicitly initialize the base class 'Person' which does not have a default constructor
newPerson (newPerson&& p) : name(std::move(p.name)) {
^
specialmemtmplMain.cpp:5:7: note: 'Person' declared here
class Person
^
2 errors generated.
So, my question is, I have not instantiated anything of newPerson class. Then why is the error refers to newPerson constructors ? What is really going on here ?
Aucun commentaire:
Enregistrer un commentaire