I've extended QDataStream with a template conversion operator so that the datastream loads from itself and converts to any supported type, as such:
class ConvertibleQDataStream : public QDataStream
{
public:
using QDataStream::QDataStream;
template <class T>
explicit operator T ()
{
T t;
*this >> t;
return t;
}
};
And one can add support to types not supported by QDataStream by overloading operator >>, as such:
template <class T>
ConvertibleQDataStream&
operator >> (ConvertibleQDataStream& ds, std::vector<T>& v)
{
//Called for std::vector's.
return ds;
}
The idea is to be able to construct non-default constructible classes directly from a stream, like this:
class Bar
{
public:
Bar(ConvertibleQDataStream&);
};
class Foo
{
int mInt;
std::vector<double> mVector;
Bar mBar;
public:
Foo(ConvertibleQDataStream& ds) :
mInt(ds), //Calls operator >> for int and converts to int
mVector(ds), //Calls operator >> for std::vector<T> and converts to std::vector<T>
mBar(ds) //Plain constructor call
{}
};
This works great except when a member is a std::optional
. std::optional
's forwarding constructor is called in stead of ConvertibleQDataStream
's template conversion operator:
template <class T>
ConvertibleQDataStream&
operator >> (ConvertibleQDataStream& ds, std::optional<T>& o)
{
//Never called :(
return ds;
}
class Qux
{
std::optional<Bar> mOptional;
public:
Foo(ConvertibleQDataStream& ds) :
mOptional(ds) //calls Bar::Bar(ConvertibleQDataStream&) rather then operator >> for std::optional<T> due to forwarding c'tor.
{}
};
Can one disable std::optional
's forwarding constructor? Or another workaround for this.
This isn't a problem with option, this is a problem in your design where mOptional is constructable from ConvertibleQDataStream.
C++ conversion rules can be a nightmare and should likely be avoided in this case by providing explicit get operators.
class ConvertibleQDataStream : public QDataStream
{
public:
using QDataStream::QDataStream;
template <class T>
T Get() const
{
T t;
*this >> t;
return t;
}
};
class Qux
{
std::optional<Bar> mOptional;
public:
Foo(ConvertibleQDataStream& ds) :
mOptional(ds.Get<std::optional<Bar>>())
{}
};