名の引数は、その後できるだけ早いそこから移動移動-からするために、いくつかの特徴的な方法で、少なくともコンストラクタ
A::A(std::string val_moved_from):
_val(std::move(val_moved_from))
{
std::cout << val_moved_from << std::endl; // Bug, but obvious
}
の実装内である(建設リストで、言います) 。
このような長い構造リストをお持ちの場合は、val_moved_from
の2つの用途が不足する可能性がありますが、これは役に立ちません。
この問題を解決するための提案を書くこともできます。 C++を拡張して、ローカル変数の型やスコープを操作で変更できるようにします。std::safe_move(X)
はX
から移動し、有効範囲外の有効期限切れの変数としてX
とマークします。変数が半分期限切れになったとき(1つのブランチで期限切れになっているが、別のブランチでは期限切れになっている)に何をすべきかは、興味深い質問です。
これは非常識なので、代わりにライブラリの問題として攻撃することができます。ある限られた範囲では、実行時にそのような種類のトリック(型が変わる変数)を偽造することができます。これは、原油ですが、アイデアを提供します:
template<typename T>
struct read_once : std::tr2::optional<T> {
template<typename U, typename=typename std::enable_if<std::is_convertible<U&&, T>::value>::type>
read_once(U&& u):std::tr2::optional<T>(std::forward<U>(u)) {}
T move() && {
Assert(*this);
T retval = std::move(**this);
*this = std::tr2::none_t;
return retval;
}
// block operator*?
};
にすなわち、唯一move
を経由してから読み取ることができるリニア型を書き、その時間の後Assert
秒を読んだり、スローされます。
その後、あなたのコンストラクタを変更します。フォワーディングコンストラクタと
A::A(read_once<std::string> val):
_val(val.move())
{
std::cout << val << std::endl; // does not compile
std::cout << val.move() << std::endl; // compiles, but asserts or throws
}
を、あなたの周りread_once<>
ラッパーを使用して「安全」(おそらくprivate
)のバージョンを楽しみ、その後、無read_once
タイプを使用してコンストラクタをあまりばかげインターフェイスを公開することができます議論。
あなたのテストは、すべてのコードパスをカバーしている場合、あなたはあなたのread_once
変数から行くと何度もmove
よりも、だけではなく、空のstd::string
秒の素敵なAssert
秒を取得します。
は非常にいい –
「C++ 11に_move_を作った」「私はそれが間違って得ることの可能性を減らすために何ができるの?」あまりない。オブジェクトを有効ではあるが奇妙な状態にしておくのはばかげている。これはC++ 11の移動セマンティクスがばかげている理由の1つです。 –
コンストラクタの本体内で_valを使用するとどうなりますか? – Thorsten