私はstd::forward
を学んでいます。なぜC++の文字列で目的の関数を呼び出すためにstd :: forwardが必要ないのですか?
#include <iostream>
#include <typeinfo>
#include <string>
using namespace std;
class Example {
};
ostream &operator << (ostream &os, const Example &e) { os << "yes!"; return os; }
void test_forward_inner(const Example &e) { cout << "& " << e << endl; }
void test_forward_inner(Example &&e) { cout << "&& " << e << endl; }
void test_forward_inner(const string &e) { cout << "& " << e << endl; }
void test_forward_inner(string &&e) { cout << "&& " << e << endl; }
template <typename T>
void test_forward_wrapper(T &&arg) {
test_forward_inner(arg);
}
int main()
{
Example e;
test_forward_wrapper(e);
test_forward_wrapper(Example());
cout << endl;
string s("hello");
test_forward_wrapper(s);
test_forward_wrapper("hello");
return 0;
}
ここで私はtest_forward_wrapper()
からtest_forward_inner()
に左辺値と右辺値を転送しようとした:私たちは、別の関数呼び出しの引数を転送する前にstd::forward
を呼び出さない場合に何が起こるかテストするための短いプログラムを書きました。このプログラムを実行すると、出力できます:
& example
& example
& hello
&& hello
std::string
に対するS、目的の内部関数が呼び出されましたが、私自身のクラスのためにのみ左辺値のバージョンが呼び出されました。引数が内部関数に渡される前にstd::forward
を呼び出すだけで、rvalueバージョンが呼び出されます。
ここで違いは何ですか?私が知っているように、参照の折りたたみ規則に従って、ラッパーがExample()
で呼び出されたとき、T
はExample
と推定され、arg
はExample &&
となるため、内部関数の右辺のバージョンを呼び出す必要があります。
ここでstd::string
のような状況では、内部関数の正しいバージョンが呼び出されました。ここでstd::forward
を削除できますか?そうでない場合は、何が起こるのでしょうか?
重要な部分は、内側機能のみSTRING' 'への変換が発生手段'のstd :: STRING'を受け入れ、ないがラッパーは、(そう全く強制そのコールで発生していない)テンプレートであることです(内部関数へのr値参照を提供する)、転送は伴わない。 – ShadowRanger
'' hello "'は 'const char *'ではなく、 'const char [6]'で 'const char *'に崩壊することができます。 。 –
^(この状況では減衰しません) –