以下のように std::remove_reference
の可能な実装を見ました
template< class T > struct remove_reference {typedef T type;};
template< class T > struct remove_reference<T&> {typedef T type;};
template< class T > struct remove_reference<T&&> {typedef T type;};
lvalue
とrvalue reference
の特殊化があるのはなぜですか?一般的なテンプレート自体で十分ではなく、参照を削除しませんか? T&
またはT&&
専門分野で::type
を使用しようとすると、T&
またはT&&
をそれぞれ正しく取得する必要があるため、ここで混乱しています。
移動中にremove_reference<t>::type&&
にキャストする理由を説明していただけますか? (パラメーターに名前が付けられているため、移動関数内で左辺値として扱われるからですか?).
また、タイプが何であるかを見つけて印刷できる方法を教えていただけますか?たとえば、タイプrvalue
のint
の場合、int&&
が渡されたことを出力できるはずですか? (私はstd::is_same
を使用してチェックしていますが、手動で行っています。)
お時間をいただきありがとうございます。
なぜ左辺値と右辺値の参照に特化があるのですか?
プライマリテンプレートのみが存在する場合は、次のようにします。
_remove_reference<int&>::type
_
あなたに与えるでしょう:
_int&
_
そしてやって:
_remove_reference<int&&>::type
_
あなたに与えるでしょう:
_int&&
_
それはあなたが望むものではありません。左辺値参照と右辺値参照の特殊化により、渡す型引数からそれぞれ_&
_と_&&
_を取り除くことができます。
たとえば、あなたがしている場合:
_remove_reference<int&&>
_
タイプ_int&&
_は、_T&&
_特殊化で指定されたパターンに一致します。T
はint
です。特殊化により、型エイリアスtype
がT
(この場合はint
)であると定義されているため、次のようにします。
_remove_reference<int&&>::type
_
int
を提供します。
move
で_remove_reference<t>::type&&
_にキャストする理由と方法を説明できますか?
これは、move()
が次のように定義されているためです。
_ template<typename T>
T&& move(T&& t) { ... }
// ^^^
// Resolves to X& if T is X& (which is the case if the input has type X
// and is an lvalue)
_
次に、move()
の引数がX
型の左辺値である場合、戻り値の型は_X&
_になります(いわゆる「ユニバーサル参照」)。戻り値の型がalways右辺値参照であることを確認します。
move()
の目的は、入力で何を渡しても、右辺値を返すことです。戻り値の型が右辺値参照である関数の関数呼び出しは右辺値であるため、move()
が常に右辺値参照を返すようにする必要があります。
_remove_reference<T>::type&&
_を非参照型に追加すると常に右辺値参照型が生成されることが保証されるため、これが_&&
_を実行する理由です。
また、タイプを見つけて出力する方法を教えていただけますか?
ここでの「印刷」の意味がわかりません。型の名前を文字列に変換する方法を知っている移植可能な方法はありません(その型を取得する方法に関係なく)。
一方、右辺値が渡されたことを確認することが目的の場合は、次のような静的アサーションを使用できます。
_#include <type_traits>
template<typename T>
void foo(T&&)
{
static_assert(!std::is_reference<T>::value, "Error: lvalue was passed!");
// ...
}
_
これは、型X
の左辺値が渡されるときに、T
が_X&
_であると推定されるという事実に依存しています。
置換の失敗のみを生成する場合は、同等のSFINAE制約を使用することもできます。
_#include <type_traits>
template<typename T, typename std::enable_if<
!std::is_reference<T>::value>::type* = nullptr>
void foo(T&&)
{
// ...
}
_
一部のタイプをテンプレートパラメータとして扱う場合、コンパイラは最も「特殊化された」特殊化を検索します。このテンプレートにint &&を渡すと、コンパイラは_remove_reference<T&&>
_バージョンを使用します。一般的な特殊化はあなたが望むものを与えません-一般的な特殊化に_int&&
_を渡すと、型は_int&&
_になります
タイプを印刷する場合は、typeid(some_type).name()
を使用します