【发布时间】:2019-10-11 09:56:33
【问题描述】:
我使用模板转换运算符扩展了 QDataStream,以便数据流从自身加载并转换为任何支持的类型,如下所示:
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 的转发构造函数吗?或者其他解决方法。
【问题讨论】:
-
Foo(ConvertibleQDataStream& ds){ ds >> mOptional; }有什么问题? -
@alterigel:一个类可能有非默认的可构造成员。这些必须在成员初始化器列表中初始化。由于从流中提取数据的顺序很重要,因此无法将某些内容移至构造函数主体。
-
@Unimportant 你的意思是你想让
ConvertibleQDataStream::operator T()被T=std::optional<Bar>调用吗? -
@alterigel 是的,它适用于所有其他类型,但转发构造函数会妨碍。
-
标准转换优先于用户定义。
标签: c++ perfect-forwarding qdatastream stdoptional