ostream<< in PIMPL
-
Hallo,
ich frage mich, wie man in einer PIMPL-Idiom-Klasse den ostream Operator implementiert, wenn man ein Template hat.
Also in der .h:
class A { private: struct Impl; std::unique_ptr<Impl> pImpl; };Und in der .cpp:
struct Impl { int i; } A::A() : pImpl(std::make_unique<Impl>())) { pImpl->i = 20; }template <class _OStream> inline _OStream& operator<<(_OStream& os, const A& in_a) { os << .... // ??? return os; }Wir komme ich an die Member ran, wenn ich in der Header nicht auf diese zugreife (auf das i)?
-
Warum ist das ein Tenplate?
-
manni66 schrieb:
Warum ist das ein Tenplate?
Na weil ein std::ostream eigentlich ein std::basic_ostream<char> ist. Also die streams sind Templates.
Man könnte es auch so machen:template <class CharType> inline std::basic_ostream<CharType> Stream& operator<<(std::basic_ostream<CharType>& os, const A& in_a) { os << .... // ??? return os; }Aber das löst das eigentliche Problem nicht. Ich fürchte, es geht nicht, ohne die Impl bekannt zu machen. Oder Du implementierst den Operator nur für char und wchar_t. Dann kannst Du die Implementierung wieder in die cpp stecken.
-
Es braucht sowieso nur die std::ostream-Überladung, alles andere ist unnötig.
-
friend std::basic_ostream<char> &operator << (std::basic_ostream<char> &out, A const &a); friend std::basic_ostream<char32_t> &operator << (std::basic_ostream<char32_t> &out, A const &a);
-
Hallo Stefan,
wenn Du Impl public machst, gibst Du keine Informationen raus, da Du Impl weiterhin einfach in .cpp definieren kannst. Ich finde es eigentlich ungewöhnlich operator<< immer als friend zu deklarieren. Einfach ein forwarding an eine öffentliche Funktion ergibt die gewünschte Syntax:
class A { public: struct Impl; private: std::unique_ptr<Impl> pImpl; }; std::ostream& operator<<( std::ostream&, const A& );.cpp
class A::Impl { public: void print( std::ostream& ) const; }; std::ostream& operator<<( std::ostream& out, const A& a ) { a.print( out ); return out; }Wenn operator<<() aber unbedingt ein template sein muss, dann kommst Du wohl nicht darum herum, Impl im header zu definieren. Es sei den, die Liste der Instanziierungen ist übersichtlich, bekannt und klein; dann könntest Du das template auch in .cpp definieren und explizit instanzieren.
Kleiner Hinweis noch: Bezeichner, die mit einem _ anfangen, gefolgt von einem Großbuchstaben, sind für die Implementierung reserviert. Du dürftest Dich also nicht beschweren, wenn irgend eine Standardlibrary _OStream als Makro definiert.
mfg Torsten