std::move は、任意の式を右値参照に変換するユーティリティ関数であり、コピーではなくムーブセマンティクスを有効にするために使用される。以下はその簡易実装例である:
template <typename T>
constexpr typename std::remove_reference<T>::type&&
my_move(T&& value) noexcept {
return static_cast<typename std::remove_reference<T>::type&&>(value);
}
この関数は、引数の参照性を除去した型に対して右値参照を返す。これにより、呼び出し元で明示的に「このオブジェクトはもう使わないので資源を移動してよい」と指示できる。
一方、std::forward は「完全転送(perfect forwarding)」を実現するための関数で、テンプレート引数の型情報に基づいて左値または右値として転送する。その実装は以下のようになる:
template <typename T>
struct my_remove_reference {
using type = T;
};
template <typename T>
struct my_remove_reference<T&> {
using type = T;
};
template <typename T>
struct my_remove_reference<T&&> {
using type = T;
};
template <typename T>
constexpr T&& my_forward(
typename my_remove_reference<T>::type& arg) noexcept {
return static_cast<T&&>(arg);
}
template <typename T>
constexpr T&& my_forward(
typename my_remove_reference<T>::type&& arg) noexcept {
static_assert(!std::is_lvalue_reference_v<T>,
"Cannot forward an rvalue as an lvalue.");
return static_cast<T&&>(arg);
}
my_forward は、テンプレートパラメータ T の型情報を利用して、元の引数が左値か右値かを再現する。これは主にユニバーサルリファレンス(T&&)を受け取るテンプレート関数内で使用される。
以下のテストコードは、これらの自作関数の動作を検証するものである:
#include <iostream>
void process(int&) {
std::cout << "lvalue reference\n";
}
void process(int&&) {
std::cout << "rvalue reference\n";
}
template <typename T>
void testForward(T&& arg) {
process(my_forward<T>(arg));
}
int main() {
int x = 100;
testForward(1); // 右辺値 → rvalue reference
testForward(x); // 左辺値 → lvalue reference
testForward(my_move(x)); // move後 → rvalue reference
}
実行結果は以下の通り:
Rvalue reference lvalue reference Rvalue reference
この結果から、my_forward が引数の値カテゴリを正しく維持し、my_move が左辺値を右辺値に変換していることが確認できる。