verschachtelte Klassen, templates & friends
-
Hallo,
der folgende Code kompiliert nicht:
template <typename T> class Q { public: class R { template <typename U> friend bool operator==(const typename Q<U>::R& a, const typename Q<U>::R& b); }; }; template <typename U> bool operator==(const typename Q<U>::R& a, const typename Q<U>::R& b) { return true; } int main() { Q<int>::R a, b; a == b; }
21:6: error: invalid operands to binary expression ('Q<int>::R' and 'Q<int>::R') 13:6: note: candidate template ignored: couldn't infer template argument 'U'
Wie kann ich den Fehler beheben?
-
Das funktioniert nicht, weil das Template-Argument in dem nested-name-specifier vorkommt. Das ist ein sog. 'non-deduced context'.
If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
The non-deduced contexts are:
— The nested-name-specifier of a type that was specified using a qualified-id.
-
Der kann den Templateparameter U nicht auflösen, weil der nicht genau weiß wie sich die Klassen bei verschiedenen Spezialisierungen verhalten.
Lösung:template <typename T> class Q { public: class R { friend bool operator==(const typename Q<T>::R& a, const typename Q<T>::R& b) { return true; } }; };
operator== gehört somit direkt zu R und kann via ADL gefunden werden.
-
Ok, das macht auch irgendwie Sinn. Also ist die einzige Möglichkeit die Funktion direkt in der Klasse zu definieren?
-
Ein einfacher Fix dafür ist
template <typename T> struct Q { struct R { friend bool operator==(const R& a, const R& b) { return true; } }; }; int main() { Q<int>::R a, b; a == b; }
Die Operatorfunktion wird dabei durch ADL gefunden und ist kein Template.
Edit: Das gibt es gar nicht, da schreibe ich glatt genau was Nathan schon schrieb...
-
Arcoth schrieb:
Das gibt es gar nicht, da schreibe ich glatt genau was Nathan schon schrieb...
:p