Using a mixin (?) to make stream i/o easier
Since many students I work with on common code have some problems comprehending proper stream operator overloading, I tried to create a helper template (don't know if this is a real mixin) to facilitate the code and insure correct operator implementation. Here it comes:
template<typename T> struct IoEnabled {
friend std::ostream& operator<<(std::ostream& out, T const& val) {
return val.print(out);
}
friend std::istream& operator>>(std::istream& in, T& val) {
return val.scan(in);
}
friend QTextStream& operator<<(QTextStream& out, T const& val) {
return val.print(out);
}
friend QTextStream& operator>>(QTextStream& in, T& val) {
return val.scan(in);
}
friend QDebug operator<<(QDebug dbg,T const& val){
std::stringstream myStream;
myStream << val;
dbg.nospace() << myStream.str().c_str();
return dbg;
}
};
Inheriting class:
class Foo: private IoEnabled<Foo> {
protected:
int mData;
public:
template<typename U>
U& scan(U& in) {
in >> mData;
return in;
}
template<typename U>
U& print(U& out) const {
out << mData;
return out;
}
}
The downsides of this implementation as far as I see them at the moment:
- Does not work for 3rd party types
- Includes inheritance and thus tight coupling with the IoClass although not every user might need Io for a certain type
The ups:
- It works ;-)
- Similar stream classes can be added without modifying all classes and withou writing specific new code for every class
Since I'm not very experienced in the usage of mixins and tend to violate coding guidelines once in a while, I'd like to know if this is an appropriate usage of 开发者_高级运维a mixin or how one could obtain a similar effect with another more suitable technique.
Many Thanks, Martin
If they can write scan
and print
template functions, they might as well write templated operators directly, skipping this entire silly mixin business.
struct Foo {
int mData;
Foo() : mData(mData) {}
};
template <typename OutputStream>
OutputStream& operator<<(OutputStream& stream, const Foo& data) {
stream << data.mData;
return stream;
}
template <typename InputStream>
InputStream& operator>>(InputStream& stream, Foo& data) {
stream >> data.mData;
return stream;
}
Also, that special-cased QDebug overload looks entirely unnecessary and wrong.
精彩评论