在本网站上的各种答案之后,我尝试定义自己的模板函数,将任何枚举值写入QDataStream。
template <typename T, typename std::enable_if_t<std::is_enum<T>::value>>
QDataStream &operator<<(QDataStream& stream, T enumValue)
{
stream << static_cast<std::underlying_type_t<T>>(enumValue);
return stream;
}
enum class MyEnum_e : int16_t{};
QDataStream stream;
MyEnum_e value;
stream << value; // Doesn't work
但我无法让它发挥作用。编译失败,并显示以下消息:
不匹配&#39;运营商&lt;&lt;&#39; (操作数类型是&#39; QDataStream&#39;和 &#39; MyEnum_e&#39;)流&lt;&lt;值;
为每个枚举定义函数我按预期工作。我使用enable_if
错了吗?
答案 0 :(得分:3)
您需要enable_if_t
作为模板参数的默认值。
template <typename T, typename U=std::enable_if_t<std::is_enum<T>::value>>
QDataStream &operator<<(QDataStream& stream, T enumValue)
{
stream << static_cast<std::underlying_type_t<T>>(enumValue);
return stream;
}
答案 1 :(得分:0)
解决方案from aschepler above是C ++ 14。以下解决方案均适用于C ++ 11。
1。根据aschepler的回答:
template <typename T, typename U=std::enable_if<std::is_enum<T>::value>>
QDataStream &operator<<(QDataStream& stream, T enumValue)
{
using underlying_type_t = typename std::underlying_type<T>::type;
stream << static_cast<underlying_type_t>(enumValue);
return stream;
}
请参见此处,此处不需要 enable_if_t
,enable_if
就足够了。
aschepler在他的第一句话中提到的使用C ++ 11时,请勿使用此解决方案。
2。下一个解决方案基于返回类型
返回类型???是的,您可能希望在参数上使用enable_if
,但不适用于运算符重载:请参见cppreference:
std :: enable_if可用作附加函数参数(不适用于运算符重载),返回类型(不适用于构造函数和析构函数)或用作类模板或函数模板参数。
template <typename T>
typename std::enable_if<std::is_enum<T>::value, QDataStream&>::type
operator<<(QDataStream& stream, T enumValue)
{
using underlying_type_t = typename std::underlying_type<T>::type;
stream << static_cast<underlying_type_t>(enumValue);
return stream;
}
请注意,此处typename std::enable_if<...>::type
是必需的,因为需要返回类型。
答案 2 :(得分:0)
由于我是在尝试将enum Type : quint8 {...}
与QSettings
进行流传输时发现此问题的,因此这两种方法都是完整的。
template<class T, typename std::enable_if<std::is_enum<T>::value, T>::type* = nullptr>
QDataStream &operator<<(QDataStream& stream, const T &enumValue)
{
return stream << static_cast<std::underlying_type_t<T>>(enumValue);
}
template<class T, typename std::enable_if<std::is_enum<T>::value, T>::type* = nullptr>
QDataStream &operator>>(QDataStream& stream, T &enumValue)
{
std::underlying_type_t<T> val;
stream >> val;
enumValue = static_cast<T>(val);
return stream;
}
对于QSettings
类型enum
,流操作符也必须在Qt元对象系统中注册。枚举用Q_ENUM()
(在QObject
或Q_GADGET
中)或Q_ENUM_NS()
(在命名空间中)或其他情况下的QT_DECLARE_METATYPE()
注册。流操作符需要分别向qRegisterMetaTypeStreamOperators<Type>("Type")
注册。还要注意,对于QFlags
,已经定义了流运算符,但是AFAIK仍需要向qRegisterMetaTypeStreamOperators
注册它们才能自动流传输。