如何防止右值和左值成员函数之间的代码重复?
How do I prevent code repeat between rvalue and lvalue member functions?
对于下面的程序代码,我必须在接收右值和左值引用的一对成员函数中编写相同的代码。
我的目标是只使用一对中的一个(例如;只使用接受右值的),以及其他的。我看了std::forward
的参考资料,据我了解,好像就是为了这个目的。但是,当我删除左值引用时,出现以下编译器错误。
'TestClass::TestClass(const TestClass &)': cannot convert argument 1 from 'std::wstring' to 'std::wstring &&'
如何防止此代码重复?
#include <iostream>
#include <string>
class TestClass
{
public:
TestClass(const std::wstring & Text)
: Text(Text)
{
std::wcout << L"LValue Constructor : " << Text << std::endl;
/*Some code here...*/
}
TestClass( std::wstring && Text)
: Text(std::forward<std::wstring>(Text))
{
std::wcout << L"RValue Constructor : " << this->Text << std::endl;
/*Same code here...*/
}
TestClass(const TestClass & Another)
: Text(Another.Text)
{
std::wcout << L"Copy Constructor : " << Text << std::endl;
/*Some code here...*/
}
TestClass( TestClass && Another)
: Text(std::forward<std::wstring>(Another.Text))
{
std::wcout << L"Move Constructor : " << Text << std::endl;
/*Same code here...*/
}
private:
std::wstring Text;
};
int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
std::wstring Argument(L"Testing Copy");
TestClass Class1Copy(Argument);
TestClass Class1Move(L"Testing Move");
TestClass Class2Copy(Class1Copy);
TestClass Class2Move(std::move(Class1Move));
_wsystem(L"pause");
return 0;
}
输出:
LValue Constructor : Testing Copy
RValue Constructor : Testing Move
Copy Constructor : Testing Copy
Move Constructor : Testing Move
Press any key to continue . . .
我认为您不能这样做,因为函数的签名决定了它们的使用时间和位置。就像 copy constructor
和 assignment operator
。他们做有些类似的事情,但编译器会根据上下文调用适当的一个。
如果您想避免重复使用代码,只需将通用性分解为一个单独的函数即可。
您可以按值取值,然后 move
。那么你只需要 N
重载,而不是 2N
:
TestClass(std::wstring Text)
: Text(std::move(Text))
{
}
你可以通过什么都不写来避免复制构造函数和移动构造函数的重复;在这种情况下,编译器将默认生成它们。
如果move构造预计会非常便宜,你可以take by value和move-from value。这比一对复制和移动重载多了 1 个移动。
如果你想要最佳效率,and/or如果移动构造便宜但便宜不足以忽略,你可以转发:
template<class T>
std::decay_t<T> copy(T&& t) {
return std::forward<T>(t);
}
class TestClass {
public:
TestClass(std::wstring const& Text)
TestClass( copy(Text) )
{}
TestClass(TestClass const& o)
: TestClass( o.Text )
{}
TestClass(TestClass&& o)
: TestClass( std::move(o).Text ) // pattern does the right thing more often than `std::move(o.Text)` does.
{}
// only "real" ctor:
TestClass( std::wstring&& Text)
: Text(std::forward<std::wstring>(Text))
{
std::wcout << L"RValue Constructor : " << this->Text << std::endl;
/*Code here...*/
}
// ...
现在一切都转发给一个构造函数。
您甚至可以混合使用这两种技术:对 std::wstring
使用按值(因为我们知道移动成本低)并为 TestClass
代码(或任何东西)做转发不太可能稳定)。
对于下面的程序代码,我必须在接收右值和左值引用的一对成员函数中编写相同的代码。
我的目标是只使用一对中的一个(例如;只使用接受右值的),以及其他的。我看了std::forward
的参考资料,据我了解,好像就是为了这个目的。但是,当我删除左值引用时,出现以下编译器错误。
'TestClass::TestClass(const TestClass &)': cannot convert argument 1 from 'std::wstring' to 'std::wstring &&'
如何防止此代码重复?
#include <iostream>
#include <string>
class TestClass
{
public:
TestClass(const std::wstring & Text)
: Text(Text)
{
std::wcout << L"LValue Constructor : " << Text << std::endl;
/*Some code here...*/
}
TestClass( std::wstring && Text)
: Text(std::forward<std::wstring>(Text))
{
std::wcout << L"RValue Constructor : " << this->Text << std::endl;
/*Same code here...*/
}
TestClass(const TestClass & Another)
: Text(Another.Text)
{
std::wcout << L"Copy Constructor : " << Text << std::endl;
/*Some code here...*/
}
TestClass( TestClass && Another)
: Text(std::forward<std::wstring>(Another.Text))
{
std::wcout << L"Move Constructor : " << Text << std::endl;
/*Same code here...*/
}
private:
std::wstring Text;
};
int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
std::wstring Argument(L"Testing Copy");
TestClass Class1Copy(Argument);
TestClass Class1Move(L"Testing Move");
TestClass Class2Copy(Class1Copy);
TestClass Class2Move(std::move(Class1Move));
_wsystem(L"pause");
return 0;
}
输出:
LValue Constructor : Testing Copy
RValue Constructor : Testing Move
Copy Constructor : Testing Copy
Move Constructor : Testing Move
Press any key to continue . . .
我认为您不能这样做,因为函数的签名决定了它们的使用时间和位置。就像 copy constructor
和 assignment operator
。他们做有些类似的事情,但编译器会根据上下文调用适当的一个。
如果您想避免重复使用代码,只需将通用性分解为一个单独的函数即可。
您可以按值取值,然后 move
。那么你只需要 N
重载,而不是 2N
:
TestClass(std::wstring Text)
: Text(std::move(Text))
{
}
你可以通过什么都不写来避免复制构造函数和移动构造函数的重复;在这种情况下,编译器将默认生成它们。
如果move构造预计会非常便宜,你可以take by value和move-from value。这比一对复制和移动重载多了 1 个移动。
如果你想要最佳效率,and/or如果移动构造便宜但便宜不足以忽略,你可以转发:
template<class T>
std::decay_t<T> copy(T&& t) {
return std::forward<T>(t);
}
class TestClass {
public:
TestClass(std::wstring const& Text)
TestClass( copy(Text) )
{}
TestClass(TestClass const& o)
: TestClass( o.Text )
{}
TestClass(TestClass&& o)
: TestClass( std::move(o).Text ) // pattern does the right thing more often than `std::move(o.Text)` does.
{}
// only "real" ctor:
TestClass( std::wstring&& Text)
: Text(std::forward<std::wstring>(Text))
{
std::wcout << L"RValue Constructor : " << this->Text << std::endl;
/*Code here...*/
}
// ...
现在一切都转发给一个构造函数。
您甚至可以混合使用这两种技术:对 std::wstring
使用按值(因为我们知道移动成本低)并为 TestClass
代码(或任何东西)做转发不太可能稳定)。