Ihre Funktion übernimmt eine rvalue Referenz aber Sie vorbei eine L-Wert - Left<T, Alloc>&&
ist nicht eine Weiterleitung Referenz, so dass es als solche Behandlung mit std::forward
usw. ist nicht korrekt. Vorerst werden wir Sammlung rvalues nicht zulassen, um die Dinge zu vereinfachen:
template<
typename T,
typename Alloc,
template<typename, typename> class Left
>
Left<T, Alloc>& operator <<(Left<T, Alloc>& coll, T&& value) {
coll.push_back(std::forward<T>(value));
return coll;
}
Die oben einen Schritt näher, aber will not work wenn ein L-Wert für value
geben. Eine Möglichkeit ist es, das richtige Argument zu zwingen, für Left
:
template<
typename T,
typename Alloc,
template<typename, typename> class Left
>
Left<typename std::decay<T>::type, Alloc>&
operator <<(Left<typename std::decay<T>::type, Alloc>& coll, T&& value) {
coll.push_back(std::forward<T>(value));
return coll;
}
Online Demo
Dies funktioniert, aber nicht lassen Sie uns eine einfache Möglichkeit Sammlung rvalues zu unterstützen. Die richtige Lösung hier IMO ist mit Template-Vorlagen zu stoppen und entweder static_assert
, dass die value_type
Matches des Containers T
oder SFINAE der Bediener weg, wenn dies nicht der Fall:
template<typename Coll, typename T>
Coll& operator <<(Coll& coll, T&& value) {
static_assert(std::is_same<
typename std::decay<T>::type,
typename Coll::value_type
>::value,
"T does not match Coll::value_type"
);
coll.push_back(std::forward<T>(value));
return coll;
}
Online Demo
oder
template<typename Coll, typename T>
typename std::enable_if<std::is_same<
typename std::decay<T>::type,
typename Coll::value_type
>::value,
Coll&
>::type
operator <<(Coll& coll, T&& value) {
coll.push_back(std::forward<T>(value));
return coll;
}
Online Demo
Mit diesem Schritt, jetzt, wenn Sie entscheiden, dass Sie Sammlung Rvalues schließlich unterstützen möchten, ist dies trivial; die static_assert
Implementierung als Beispiel zu verwenden:
template<typename Coll, typename T>
Coll&& operator <<(Coll&& coll, T&& value) {
static_assert(std::is_same<
typename std::decay<T>::type,
typename std::decay<Coll>::type::value_type
>::value,
"T does not match Coll::value_type"
);
coll.push_back(std::forward<T>(value));
return std::forward<Coll>(coll);
}
Online Demo
N. B. die obige Implementierung erlaubt nur die Verwendung des Operators mit genauen Treffer-Coll::value_type
, aber es ist wahrscheinlich sinnvoll, etwas zu ermöglichen, die umgewandeltColl::value_type
sein kann - dies umzusetzen, ersetzen Sie einfach std::is_same
mit std::is_convertible
.
Warum ist Links <...> && keine Weiterleitungsreferenz? (Warum wird dies nicht als eine Art deduzierende Situation betrachtet?) – kfsone
@kfsone: Der Standard definiert eine Weiterleitungsreferenz als "eine rvalue-Referenz auf einen cv-unqualifizierten Vorlagenparameter"; Ein spezieller Template-Template-Parameter ist nicht mit einem Template-Parameter identisch. : -] – ildjarn
Danke für die Erklärung. Ich kann sehen, dass dies eine häufige Quelle von Missverständnissen ist – kfsone