我已经使用模板转换运算符扩展了qdatastream,以便dataStream从自身加载并转换为任何支持类型,因此:
class ConvertibleQDataStream : public QDataStream
{
public:
using QDataStream::QDataStream;
template <class T>
explicit operator T ()
{
T t;
*this >> t;
return t;
}
};
可以通过超载操作员>>来添加支持qdatastream不支持的类型的支持:
template <class T>
ConvertibleQDataStream&
operator >> (ConvertibleQDataStream& ds, std::vector<T>& v)
{
//Called for std::vector's.
return ds;
}
这个想法是能够直接从流中直接构建非默认构造类,例如:
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
{}
};
这很好,除非成员是std::optional
。std::optional
的转发构造器被称为ConvertibleQDataStream
的模板转换操作员:
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.
{}
};
一个人可以禁用std::optional
的转发构造函数吗?或另一个解决方法。
这不是选项的问题,这在您的设计中是一个问题,可以从convertibleqdatastream构造moptional。
c 转换规则可以是噩梦,在这种情况下,应避免通过明确获取操作员来避免。
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>>())
{}
};