Name Argumente, dessen Zweck es ist, in einem gewissen unverwechselbaren Art und Weise eingefahrene von werden, zumindest im Rahmen der Umsetzung des Konstrukteurs
A::A(std::string val_moved_from):
_val(std::move(val_moved_from))
{
std::cout << val_moved_from << std::endl; // Bug, but obvious
}
dann von ihnen so früh wie möglich bewegen (in der Konstruktionsliste, sagt) .
Wenn Sie solch eine lange Konstruktionsliste haben, können Sie zwei Verwendungen von val_moved_from
darin vermissen, das hilft nicht.
Eine Alternative wäre, einen Vorschlag zu schreiben, um dieses Problem zu beheben. Nehmen wir an, Sie erweitern C++ so, dass die Typen oder Bereiche lokaler Variablen durch Operationen an ihnen geändert werden können. Daher verschiebt sich std::safe_move(X)
von X
und markiert X
als abgelaufene Variable, die für den Rest des Gültigkeitsbereichs nicht mehr gültig ist. Herauszufinden, was zu tun ist, wenn eine Variable halb abgelaufen ist (abgelaufen in einem Zweig, aber nicht in einem anderen Zweig), ist eine interessante Frage.
Weil das verrückt ist, können wir es stattdessen als ein Bibliotheksproblem angreifen. Bis zu einem gewissen Grad können wir diese Art von Tricks (eine Variable, deren Typ sich ändert) zur Laufzeit fälschen. Das ist grob, aber gibt die Idee:
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*?
};
dh schreiben einen linearen Typ, der nur von über move
gelesen werden kann, und nach dieser Zeit mit dem Lesen Assert
s oder wirft.
ändern Sie dann Ihren Konstruktor:
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
}
mit Speditions Konstrukteurs können Sie eine weniger lächerlich Schnittstelle ohne read_once
Arten aussetzen, dann uns auf Ihre Konstrukteure auf Ihre „sicher“ (möglicherweise private
) Versionen mit read_once<>
Wrapper um die Argumente.
Wenn Ihre Tests alle Codepfade decken, werden Sie Assert
s statt nur leer std::string
ist schön, auch wenn Sie gehen und move
mehr als einmal von Ihrem read_once
Variablen.
"machte die _move_ bis C 11 ++" very nice –
"Was kann ich die Chancen auf es falsch zu reduzieren tun?" Nicht viel. Objekte in gültigen, aber seltsamen Zuständen zu belassen, ist lächerlich, was ein Grund dafür ist, dass die Umzugs-Semantik von C++ 11 albern ist. –
Was ist falsch an der Verwendung von _val im Körper des Konstruktors? – Thorsten