tho*_*ter 3 c++ templates operator-overloading c++11
我正在尝试使用C++ 11枚举类创建标志位域.我正在寻找一种方法来模拟运算符的返回类型,以便它们可以在下面的代码中使用:
#include <iostream>
enum class Flags {
one = 1,
two = 1 << 1,
three = 1 << 2,
four = 1 << 3
};
#define _CONVERT(_operator) \
static_cast<T>(static_cast<int>(lhs) _operator static_cast<int>(rhs))
template <typename T>
T operator & (const Flags& lhs, const Flags& rhs) {
return _CONVERT(&);
}
template <typename T>
T operator | (const Flags& lhs, const Flags& rhs) {
return _CONVERT(|);
}
#undef _convert
int main()
{
Flags flag = Flags::one | Flags::two | Flags::three;
if (flag & Flags::two)
std::cout << "Flag has two" << std::endl;
if (flag & Flags::four)
std::cout << "Flag has four" << std::endl;
std::cout << static_cast<int>(flag) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
但是,有几个问题:
Flags flag = Flags::one | Flags::two | Flags::three; 不能推断出类型 Flagsif (flag & Flags::four) 不能推断出类型 bool我是模板的新手,在模板演绎机制方面有点丢失.此外,我试图创建创建转换运算符
operator bool(const Flags& flag)
Run Code Online (Sandbox Code Playgroud)
但没有结果.
首先创建一个帮助器模板:
template<class E>
struct bool_or_enum{
E e;
explicit operator bool()const{return static_cast<bool>(e); }
operator E() const {return e;}
};
Run Code Online (Sandbox Code Playgroud)
接下来,创建一个特征函数并输入:
namespace magic_operators {
template<class E>
constexpr std::false_type algebraic_enum(E const volatile&) {return {};}
template<class E>
using use_algebra=decltype( algebraic_enum( std::declval<E const volatile&>() ) );
}
Run Code Online (Sandbox Code Playgroud)
现在magic_operators::use_algebra<E>搜索使用ADL的algebraic_enum过载恢复std::true_type上E.这允许在任何地方启用魔法.MSVC 2015缺乏足够的C++ 11支持来使用上述功能; 替换为traits类.
肉:我们的经营者.将它们粘贴到命名空间中并将它们带入using namespace:
template<class E, std::enable_if_t<magic_operators::use_algebra<E>{}, int> = 0>
bool_or_enum<E> operator&(E const& lhs, E const& rhs){
using U = std::underlying_type_t<E>;
return { E( static_cast<U>(lhs) | static_cast<U>(rhs) ) };
}
Run Code Online (Sandbox Code Playgroud)
和类似的|.
对于~和^你需要一个位掩码保持定义的行为.有一个特权类enum_mask<E>,默认为E::bit_mask或某些得到它.
template<class E, std::enable_if_t<magic_operators::use_algebra<E>{}, int> = 0>
bool_or_enum<E> operator^(E const& lhs, E const& rhs){
using U = std::underlying_type_t<E>;
return { E( enum_mask<E>{} & (static_cast<U>(lhs) ^ static_cast<U>(rhs) ) ) };
}
template<class E, std::enable_if_t<magic_operators::use_algebra<E>{}, int> = 0>
bool_or_enum<E> operator~(E const& e){
using U = std::underlying_type_t<E>;
return { E( enum_mask<E>{} & (~static_cast<U>(e)) ) };
}
Run Code Online (Sandbox Code Playgroud)
由于超出色域枚举的标准要求,这很棘手.
|=而&=并不难,但是需要进行编码.=和|=和&=等同时支持分配链和隐式布尔还需要更多的工作.我说不支持它.
哦,标记一切,constexpr并bool_or_enum<E>为operators 添加重载.
以上代码未经过测试或编译,但设计有效.
最终结果是:
enum class Bob { a=2, b=7, bit_mask = 0x00ff };
constexpr std::true_type algebraic_enum( Bob const& ){ return {}; }
using namespace algebraic_ops;
int main(){
Bob x=Bob::a;
x = x | Bob::b;
if( x &~ Bob::b ){
std::cout << "cast to bool bitmasking!\n";
}
}
Run Code Online (Sandbox Code Playgroud)
或者某些人.
| 归档时间: |
|
| 查看次数: |
397 次 |
| 最近记录: |