【发布时间】:2020-03-18 10:35:39
【问题描述】:
我正在实现一个使用命名参数惯用语来初始化其成员的类:
class Person
{
public:
Person & first_name(std::string n) { m_first_name = n; return *this; }
Person & last_name(std::string l) { m_last_name = l; return *this; }
Person & age(int a) { m_age = a; return *this; }
std::string get_first_name() const { return m_first_name; }
std::string get_last_name() const { return m_last_name; }
int get_age() const { return m_age; }
private:
std::string m_first_name;
std::string m_last_name;
int m_age;
};
到目前为止,一切正常。
#include <string>
#include <iostream>
class Person
{
public:
Person & first_name(std::string n) { m_first_name = n; return *this; }
Person & last_name(std::string l) { m_last_name = l; return *this; }
Person & age(int a) { m_age = a; return *this; }
std::string get_first_name() const { return m_first_name; }
std::string get_last_name() const { return m_last_name; }
int get_age() const { return m_age; }
private:
std::string m_first_name;
std::string m_last_name;
int m_age;
};
void print(Person const & p)
{
std::cout << p.get_last_name() << ", " << p.get_first_name() << ", " << p.get_age() << '\n';
}
int main()
{
auto p1 = Person().first_name("Joe").age(20);
auto p2 = Person().last_name("Kane").age(50);
print(p1);
print(p2);
}
以上代码输出
, Joe, 20
Kane, , 50
正如预期的那样。
但是,一旦我使我的类不可复制(在我的情况下,通过添加 std::unique_ptr 成员),上面的代码将无法编译
#include <string>
#include <memory>
#include <iostream>
class Person
{
public:
Person & first_name(std::string n) { m_first_name = n; return *this; }
Person & last_name(std::string l) { m_last_name = l; return *this; }
Person & age(int a) { m_age = a; return *this; }
std::string get_first_name() const { return m_first_name; }
std::string get_last_name() const { return m_last_name; }
int get_age() const { return m_age; }
private:
std::string m_first_name;
std::string m_last_name;
int m_age;
std::unique_ptr<int> m_ptr; // added member
};
void print(Person const & p)
{
std::cout << p.get_last_name() << ", " << p.get_first_name() << ", " << p.get_age() << '\n';
}
int main()
{
auto p1 = Person().first_name("Joe").age(20);
auto p2 = Person().last_name("Kane").age(50);
print(p1);
print(p2);
}
G++ 出现以下错误:
prog.cc: In function 'int main()':
prog.cc:30:48: error: use of deleted function 'Person::Person(const Person&)'
30 | auto p1 = Person().first_name("Joe").age(20);
| ^
prog.cc:5:7: note: 'Person::Person(const Person&)' is implicitly deleted because the default definition would be ill-formed:
5 | class Person
| ^~~~~~
prog.cc:5:7: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]'
In file included from /opt/wandbox/gcc-head/include/c++/10.0.0/memory:82,
from prog.cc:2:
/opt/wandbox/gcc-head/include/c++/10.0.0/bits/unique_ptr.h:456:7: note: declared here
456 | unique_ptr(const unique_ptr&) = delete;
| ^~~~~~~~~~
prog.cc:31:48: error: use of deleted function 'Person::Person(const Person&)'
31 | auto p2 = Person().last_name("Kane").age(50);
|
我通过返回右值解决了这个问题:
class Person
{
public:
Person && first_name(std::string n) { m_first_name = n; return std::move(*this); }
Person && last_name(std::string l) { m_last_name = l; return std::move(*this); }
Person && age(int a) { m_age = a; return std::move(*this); }
// ...
};
这是正确的解决方法吗?有什么我应该考虑的陷阱吗?
【问题讨论】: