私は右辺値をサポートし、セマンティクスを移動するために、テンプレート ファクトリ関数を std::forward を使用する (そして理解する) ように切り替えてきました。テンプレート クラスの通常のボイラープレート ファクトリ関数は、常にパラメーターを const としてマークしています。
#include <iostream>
#include <utility>
template<typename T, typename U>
struct MyPair{
MyPair(const T& t, const U& u):t(t),u(u){};
T t;
U u;
};
template<typename T, typename U>
std::ostream& operator<<(std::ostream& os, const MyPair<T,U>& pair){
os << "(" << pair.t << ")=>" << pair.u;
return os;
}
template<typename T, typename U>
MyPair<T,U> MakeMyPair(const T& t, const U& u){
return MyPair<T,U>(t,u);
}
using namespace std;
int main(int argc, char *argv[]) {
auto no_forward = MakeMyPair(num, num);
std::cout << no_forward << std::endl;
auto no_forward2 = MakeMyPair(100, false);
std::cout << no_forward2 << std::endl;
}
期待どおりにコンパイルされます。最初に MakeMyPair を変換してパラメータも const として渡しましたが、これは XCode 4.6 を使用している Mac ではコンパイルされません。
//$ clang --version
//Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
//Target: x86_64-apple-darwin12.2.0
//Thread model: posix
template<typename T, typename U>
MyPair<T,U> MakeMyPair_Forward(const T&& t, const U&& u){
return MyPair<T,U>(std::forward<const T>(t),std::forward<const U>(u));
}
int main(int argc, char *argv[]) {
int num = 37;
auto anotherPair = MakeMyPair_Forward(num, true); //This won't work
auto allRvalues = MakeMyPair_Forward(73, false); //will compile
std::cout << allRvalues << std::endl;
}
'MakeMyPair_Forward' の呼び出しに一致する関数がありません 候補関数 [T = int、U = bool] は実行できません: 第 1 引数の 'int' から 'const int &&' への既知の変換はありません
これはhttp://en.cppreference.com/w/cpp/utility/forwardから理にかなっています。これは const が推定され、左辺値を渡していることを示しています。
- wrapper() への呼び出しが右辺値 std::string を渡す場合、T は std::string (std::string&、const std::string&、または std::string&& ではない) と推定され、std::forward は保証します。右辺値参照が foo に渡されます。
- wrapper() への呼び出しが const 左辺値 std::string を渡す場合、T は const std::string& と推定され、std::forward は const 左辺値参照が foo に渡されることを保証します。
- wrapper() への呼び出しが非 const 左辺値 std::string を渡す場合、T は std::string& と推定され、std::forward は非 const 左辺値参照が foo に渡されることを保証します。
const の削除は、右辺値と左辺値で必要に応じて機能します。MakeMyPair_Forward のパラメーターの const で機能するのは、右辺値を型として渡すことだけです。
//This works for rvalues and lvalues
template<typename T, typename U>
MyPair<T,U> MakeMyPair_Forward(T&& t, U&& u){
return MyPair<T,U>(std::forward<const T>(t),std::forward<const U>(u));
}
では、質問です。パラメータとして渡すときに右辺値参照を const としてマークすることは意味がありますか? 右辺値を変更できるわけではなく、一時的なものです。コードを調べて修正した後、 const でコンパイルされたことに少し驚きました。右辺値パラメーターを const としてマークするのはなぜですか? 右辺値を取る API のみを提供することがポイントでしょうか? もしそうなら、左辺値参照を防ぐために代わりに型特性を使用しませんか? https://stackoverflow.com/a/7863645/620304
ありがとう。