0

マイクロソフトから次のスニペットを入手しました

template <typename T> struct RemoveReference {
     typedef T type;
};

template <typename T> struct RemoveReference<T&> {
     typedef T type;
};

template <typename T> struct RemoveReference<T&&> {
     typedef T type;
};

template <typename T> typename RemoveReference<T>::type&& Move(T&& t) {
    return t;
}

..。

remote_integer x = frumple(5);
remote_integer&& x1 = Move(x);

「エラーC2440:'return':'remote_integer'から'remote_integer&&'に変換できません」というエラーが表示されます。

コンパイラで何か変更されましたか?std :: moveを使用すると、すべてがうまくいきます。

4

1 に答える 1

3

あなたMoveが機能しない理由tは、常に左辺値T&&であるためです(たとえば、に解決された場合でもint&&)。奇妙に思えるかもしれませんが、名前付き右辺値参照は実際には左辺値です。

から戻るときMove、左辺値を右辺値参照に暗黙的にバインドしようとしますが、これは標準 (§8.5.3) で禁止されています。コメントに記載されているように、t右辺値参照に明示的にキャストする必要があります。

標準の関連部分は §5/4 と §5/5 ですが、これをうまくまとめた注記 §5/6 を引用します。

一般に、このルールの効果は、名前付きの右辺値参照が左辺値として扱われ、オブジェクトへの名前のない右辺値参照が xvalue として扱われることです。関数への右辺値参照は、名前が付けられているかどうかにかかわらず、左辺値として扱われます。

正しい実装は確かに:

template <typename T>
typename std::remove_reference<T>::type&& move(T&& t)
{
  return static_cast<typename std::remove_reference<T>::type&&>(t);
}

私が覚えている限りでは、このコードは以前のドラフトで有効でした。ただし、ルールが変更されたため、明示的なキャストを提供する必要があります (同じことが std::forward にも当てはまります)。

于 2011-09-08T17:21:38.387 に答える