gpt4 book ai didi

c++ - 模板化枚举类运算符

转载 作者:太空狗 更新时间:2023-10-29 20:02:29 24 4
gpt4 key购买 nike

我正在尝试使用 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;
}

但是,有几个问题:

  • 标志 flag = Flags::one |标志::两个 | Flags::three; 无法将类型推断为 Flags
  • if (flag & Flags::four) 无法推断类型为 bool

我是模板的新手,在涉及到模板推导机制时有点不知所措。另外,我尝试创建创建转换运算符

operator bool(const Flags& flag)

但没有结果。

最佳答案

首先创建一个辅助模板:

template<class E>
struct bool_or_enum{
E e;
explicit operator bool()const{return static_cast<bool>(e); }
operator E() const {return e;}
};

接下来,创建一个特征函数并输入:

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&>() ) );
}

现在magic_operators::use_algebra<E>使用 ADL 搜索 algebraic_enum重载返回 std::true_typeE .这允许在任何地方启用魔法。 MSVC 2015 缺乏足够的 C++11 支持来使用上述内容;替换为特征类。

肉:我们的运营商。将它们粘贴到命名空间中并使用 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) ) };
}

| 类似.

对于 ~^你需要一个位掩码来保持定义的行为。有一个特质类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)) ) };
}

由于对超色域枚举的标准要求,这很棘手。

|=&=不难,但确实需要编码。 =|=&= etc 同时支持赋值链和隐式 bool 需要更多的工作。我说不支持。

哦,标记所有内容 constexpr并添加 bool_or_enum<E>重载到 operator

以上代码未经测试或编译,但设计有效。


最终结果是:

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";
}
}

或者类似的东西。

关于c++ - 模板化枚举类运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40218431/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com