Qt 5.9 中的Q_FLAG_NS不提供按位运算符



应该如何使用Q_FLAG_NS宏?

我对Q_FLAG_NS和KDAB的新Qt支持命名空间的阅读向我表明,使用此宏应该提供按位运算符,但无论我尝试什么,

../main.cpp:11:11: error: invalid operands to binary expression 
('App::ComponentRequirementState' and 'App::ComponentRequirementState')
r = r | App::ComponentRequirementState::AlwaysRequired;
~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我在这里放置了一个最小的代码示例。

奇怪的是,我可以在ComponentRequirementStat枚举的定义中使用按位运算符,只是不能在枚举之外使用。

我用这个宏错了吗? 还是根本不起作用?

当我手动定义运算符时,比如说,

auto operator|(const App::ComponentRequirementState a, App::ComponentRequirementState b) -> App::ComponentRequirementState
{
return static_cast<App::ComponentRequirementState>(static_cast<unsigned int>(a) | static_cast<unsigned int>(b));
}

然后它起作用了。

使用 Qt

Q_FLAGS_NS不提供按位操作支持:它只是在Qt元对象系统中注册类型。

如果要注册类型并提供类型安全的按位运算符支持,则应使用 QFlags。

文档中的示例如下:

class MyClass
{
public:
enum Option {
NoOptions = 0x0,
ShowTabs = 0x1,
ShowAll = 0x2,
SqueezeBlank = 0x4
};
Q_DECLARE_FLAGS(Options, Option)
...
};
Q_DECLARE_OPERATORS_FOR_FLAGS(MyClass::Options)

您也可以跳过其中的大部分内容并执行以下操作:

// not type-safe, unscoped enum. You should likely define this
// in a namespace or class.  
enum Option {
NoOptions = 0x0,
ShowTabs = 0x1,
ShowAll = 0x2,
SqueezeBlank = 0x4
};
// type-safe flag
using Options = QFlags<Option>;

您还可以将无作用域枚举用于此目的,或使用宏来帮助为作用域枚举提供按位运算符支持:

使用作用域枚举的类型安全按位操作

这是一个你可以自由使用的宏(公共领域,我自己的代码,尽管你应该修改宏以确保它有一个前缀以避免任何名称冲突)来向作用域枚举添加按位运算。这目前需要 C++14 支持,但是,将std::underlying_type_t<T>更改为typename std::underlying_type<T>::type允许宏在 C++11 中工作。

enum class enum1_t
{
A = 1,
B,
C,
D,
E,
};

enum class enum2_t
{
F = 1,
G,
H,
I,
J,
};
ENUM_FLAG(enum1_t)            // allow bitwise operations for enum1_t and enum1_t
ENUM_FLAG(enum1_t, enum2_t)   // allow bitwise operations for enum1_t and enum2_t

法典

#include <type_traits>
#include <cstdint>
// HELPERS
// -------
/**
*  brief Get enum underlying type.
*/
template <typename T>
inline std::underlying_type_t<T> int_t(T t)
{
return static_cast<std::underlying_type_t<T>>(t);
}
// MACROS
// ------
/**
*  brief Macro to define enum operators between enumerations.
*
*  Supports `&`, `&=`, `|`, `|=`, `^`, `^=`, `~`, and bool conversion.
*/
#define ENUM_FLAG2(lhs_t, ths_t)                                        
/*  brief Bitwise or operator. */                                  
inline lhs_t operator|(lhs_t lhs, ths_t rhs) noexcept               
{                                                                   
return static_cast<lhs_t>(int_t(lhs) | int_t(rhs));             
}                                                                   
  
/*  brief Bitwise or assignment operator. */                       
inline lhs_t & operator|=(lhs_t &lhs, ths_t rhs) noexcept           
{                                                                   
lhs = static_cast<lhs_t>(int_t(lhs) | int_t(rhs));              
return lhs;                                                     
}                                                                   
  
/*  brief Bitwise and operator. */                                 
inline lhs_t operator&(lhs_t lhs, ths_t rhs) noexcept               
{                                                                   
return static_cast<lhs_t>(int_t(lhs) & int_t(rhs));             
}                                                                   
  
/*  brief Bitwise and assignment operator. */                      
inline lhs_t & operator&=(lhs_t &lhs, ths_t rhs) noexcept           
{                                                                   
lhs = static_cast<lhs_t>(int_t(lhs) & int_t(rhs));              
return lhs;                                                     
}                                                                   
  
/*  brief Bitwise xor operator. */                                 
inline lhs_t operator^(lhs_t lhs, ths_t rhs) noexcept               
{                                                                   
return static_cast<lhs_t>(int_t(lhs) ^ int_t(rhs));             
}                                                                   
  
/*  brief Bitwise xor assignment operator. */                      
inline lhs_t & operator^=(lhs_t &lhs, ths_t rhs) noexcept           
{                                                                   
lhs = static_cast<lhs_t>(int_t(lhs) ^ int_t(rhs));              
return lhs;                                                     
}

/**
*  brief Set enumeration flags within the same enum.
*/
#define ENUM_FLAG1(enum_t)                                              
ENUM_FLAG2(enum_t, enum_t)                                          
  
/*  brief Bitwise negation operator. */                            
inline enum_t operator~(enum_t value) noexcept                      
{                                                                   
return static_cast<enum_t>(~int_t(value));                      
}                                                                   
  
/*  brief Negation operator. */                                    
inline bool operator!(enum_t value) noexcept                        
{                                                                   
return int_t(value) == 0;                                       
}
/**
*  brief Macros to grab the proper bit-wise flag setter.
*  `ENUM_ID` is required for MSVC compatibility, since MSVC
*  has issues in expanding `__VA_ARGS__` for the dispatcher.
*  Don't remove it, even if the above code works without it 
*  for GCC and Clang.
*/
#define ENUM_ID(x) x
#define GET_ENUM_FLAG(_1,_2,NAME,...) NAME
#define ENUM_FLAG(...) ENUM_ID(GET_ENUM_FLAG(__VA_ARGS__, ENUM_FLAG2, ENUM_FLAG1)(__VA_ARGS__))

>Q_FLAG_NS不是问题。这是由新的 C++11 作用域枚举 (enum class) 引起的。它们不会隐式转换为整型类型,并且不能将它们用于仅为整型 [1][2] 定义的按位运算。

您必须自己提供这些操作,或使用无作用域的旧枚举。

提供这些操作的一个问题是,它需要将所有可能的标志组合定义为枚举值或返回整型:

??? operator|(App::ComponentRequirementState lhs, App::ComponentRequirementState rhs);

相关内容

  • 没有找到相关文章

最新更新