以下のコードでは、std::forward
引数を渡すときになぜ使用する必要がありますか?
class Test {
public:
Test() {
std::cout << "ctor" << std::endl;
}
Test(const Test&) {
std::cout << "copy ctor" << std::endl;
}
Test(const Test&&) {
std::cout << "move ctor" << std::endl;
}
};
template<typename Arg>
void pass(Arg&& arg) {
// use arg..
return;
}
template<typename Arg, typename ...Args>
void pass(Arg&& arg, Args&&... args)
{
// use arg...
return pass(args...); // why should I use std::forward<Arg>(args)... ?
}
int main(int argc, char** argv)
{
pass(std::move<Test>(Test()));
return 0;
}
コードの有無にかかわらずstd::forward
、コピー/移動は表示されません。
何std::forward
がどのように機能するかについての良い投稿がたくさんあります(ここやここなど)。
一言で言えば、引数の値カテゴリを保持します。関数に提供された引数が、最初に提供されたものと同じ値カテゴリ(基本的にr値とl値)を持つ別の関数に転送される(または関数内で使用される)ことを保証するために、完全な転送があります。これは通常、参照の折りたたみが行われた可能性のあるテンプレート関数で使用されます(ユニバーサル/転送参照を含む)。
以下のコードサンプルを検討してください。std::forward
プリントアウトrequires lvalue
を削除し、プリントアウトを追加std::forward
しrequires rvalue
ます。func
それは右辺値または左辺値であるかどうかに基づいてオーバーロードされます。呼び出しなしでそれをstd::forward
呼び出すと、誤ったオーバーロードが呼び出されます。std::forward
この場合には必要とされてpass
右辺値と呼ばれています。
#include <utility>
#include <iostream>
class Test {
public:
Test() {
std::cout << "ctor" << std::endl;
}
Test(const Test&) {
std::cout << "copy ctor" << std::endl;
}
Test(Test&&) {
std::cout << "move ctor" << std::endl;
}
};
void func(Test const&)
{
std::cout << "requires lvalue" << std::endl;
}
void func(Test&&)
{
std::cout << "requires rvalue" << std::endl;
}
template<typename Arg>
void pass(Arg&& arg) {
// use arg here
func(std::forward<Arg>(arg));
return;
}
template<typename Arg, typename ...Args>
void pass(Arg&& arg, Args&&... args)
{
// use arg here
return pass(std::forward<Args>(args)...);
}
int main(int, char**)
{
pass(std::move<Test>(Test()));
return 0;
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加