类型安全 c++11 枚举类标志的模板

2024-01-06

我正在尝试使用模板创建类型安全的 C++ 标志。我也想区分一下a旗帜和旗帜s(零个、一个或多个标志)。

下面的解决方案效果很好,除了EnumFlag<T> operator | (T, T)这导致所有|- 对枚举进行操作以返回类型EnumFlag。这会破坏很多代码。有什么技巧可以解决这个问题吗?在我的代码中,我执行以下操作,但是硬编码Option这里没有选择。如何使这个通用?

EnumFlag<typename std::enable_if<std::is_same<T, Option>::value, T>::type> operator | (T l, T r)

将其更改为...

EnumFlag<T> operator | (T l, T r)

......原因打破了一切。我想要这样的东西(不是编译标签代码)。或者任何其他更好的想法!

EnumFlag<typename std::enable_if<std::already_expanded<EnumFlag<T>>::value, T>::type> operator | (T l, T r)

完整的可编译代码:

枚举标志.h

#ifndef __classwith_flags_h_
#define __classwith_flags_h_

#include <type_traits>

enum class Option
{
    PrintHi = 1 << 0,
    PrintYo = 1 << 1,
    PrintAlot = 1 << 2
};

template <typename T>
class EnumFlag
{
public:
    using UnderlayingType = typename std::underlying_type<T>::type;

    EnumFlag(const T& flags)
        : m_flags(static_cast<UnderlayingType>(flags))
    {}

    bool operator & (T r) const
    {
        return 0 != (m_flags & static_cast<UnderlayingType>(r));
    }

    static const T NoFlag = static_cast<T>(0);

private:
    UnderlayingType  m_flags;
};
template<typename T>
EnumFlag<typename std::enable_if<std::is_same<T, Option>::value, T>::type> operator | (T l, T r)
{
    return static_cast<T>(static_cast<typename EnumFlag<T>::UnderlayingType>(l) | static_cast<typename EnumFlag<T>::UnderlayingType>(r));
}

class ClassWithFlags
{
public:
    using Options = EnumFlag < Option >;

    void doIt(const Options &options);
};

#endif

枚举标志.c++

#include "EnumFlag.h"

#include <iostream>

void ClassWithFlags::doIt(const Options &options)
{
    if (options & Option::PrintHi)
    {
        std::cout << "Hi" << std::endl;
    }
    if (options & Option::PrintYo)
    {
        std::cout << "Yo!" << std::endl;
    }
}

int main()
{
    ClassWithFlags classWithFlags;
    classWithFlags.doIt(Option::PrintHi | Option::PrintAlot);
}

> DEMO http://coliru.stacked-crooked.com/a/985a3d21d402d2f4 <

实际的代码会包含更多的运算符,但这足以说明问题。

一种侵入性较小的解决方案是(但仍然太侵入性)

template<typename T>
typename std::underlying_type<T>::type operator | (T l, T r)
{
    return (static_cast<typename std::underlying_type<T>::type>(l) | static_cast<typename std::underlying_type<T>::type>(r));
}

那就不够神了EnumFlag(const std::underlying_type<T> &flags)必须存在,但我失去了类型安全性。另外,我希望仅为实际需要的类型创建全局运算符重载。宏也不是神,因为我希望允许声明EnumFlag在课堂上。全局重载不可能存在,因此我需要在不同位置创建两个宏调用EnumFlag.

解决方案必须是纯 C++11/stl。


安东尼·威廉姆斯 (Anthony Williams) 有一篇很好的文章,其中包含现成的代码:“使用枚举类作为位域” https://www.justsoftwaresolutions.co.uk/cplusplus/using-enum-classes-as-bitfields.html.

也许这正是您所寻找的。与我看到的其他解决方案不同,这里不使用宏 - 只是纯模板。

简单的例子展示了他的解决方案:

#include "bitmask_operators.hpp"

enum class A{
    x=1,y=2
       };

enum class B:unsigned long {
    x=0x80000000,y=0x40000000
        };

template<>
struct enable_bitmask_operators<A>{
    static const bool enable=true;
};

template<>
struct enable_bitmask_operators<B>{
    static const bool enable=true;
};

enum class C{x,y};


int main(){
    A a1=A::x | A::y;
    A a2=a1&A::y;
    a2^=A::x;
    A a3=~a1;

    B b1=B::x | B::y;
    B b2=b1&B::y;
    b2^=B::x;
    B b3=~b1;

    // C c1=C::x | C::y;
    // C c2=c1&C::y;
    // c2^=C::x;
    // C c3=~c1;
}

bitmask_operators.hpp源代码 https://www.justsoftwaresolutions.co.uk/files/bitmask_operators.hpp.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

类型安全 c++11 枚举类标志的模板 的相关文章

  • CLR 2.0 与 4.0 性能比较?

    如果在 CLR 4 0 下运行 为 CLR 2 0 编译的 NET 程序会运行得更快吗 应用程序配置
  • 适合初学者的良好调试器教程[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有谁知道一个好的初学者教程 在 C 中使用调试器 我感觉自己好像错过了很多 我知道怎么做 单步执行代码并查看局部变量 虽然这常常给我带来问
  • 使用 C# 登录《我的世界》

    我正在尝试为自己和一些朋友创建一个简单的自定义 Minecraft 启动器 我不需要启动 Minecraft 的代码 只需要登录的实际代码行 例如 据我所知 您过去可以使用 string netResponse httpGET https
  • 如何捕获未发送到 stdout 的命令行文本?

    我在项目中使用 LAME 命令行 mp3 编码器 我希望能够看到某人正在使用什么版本 如果我只执行 LAME exe 而不带参数 我会得到 例如 C LAME gt LAME exe LAME 32 bits version 3 98 2
  • 代码 GetAsyncKeyState(VK_SHIFT) & 0x8000 中的这些数字是什么?它们是必不可少的吗?

    我试图在按下按键的简单动作中找到这些数字及其含义的任何逻辑解释 GetAsyncKeyState VK SHIFT 0x8000 可以使用哪些其他值来代替0x8000它们与按键有什么关系 GetAsyncKeyState 根据文档返回 如果
  • ComboBox DataBinding 导致 ArgumentException

    我的几个类对象 class Person public string Name get set public string Sex get set public int Age get set public override string
  • 查找进程的完整路径

    我已经编写了 C 控制台应用程序 当我启动应用程序时 不使用cmd 我可以看到它列在任务管理器的进程列表中 现在我需要编写另一个应用程序 在其中我需要查找以前的应用程序是否正在运行 我知道应用程序名称和路径 所以我已将管理对象搜索器查询写入
  • JNI 将 Char* 2D 数组传递给 JAVA 代码

    我想从 C 代码通过 JNI 层传递以下指针数组 char result MAXTEST MAXRESPONSE 12 12 8 3 29 70 5 2 42 42 在java代码中我写了以下声明 public static native
  • 为什么在 WebApi 上下文中在 using 块中使用 HttpClient 是错误的?

    那么 问题是为什么在 using 块中使用 HttpClient 是错误的 但在 WebApi 上下文中呢 我一直在读这篇文章不要阻止异步代码 https blog stephencleary com 2012 07 dont block
  • 从同一个类中的另一个构造函数调用构造函数

    我有一个带有两个构造函数的类 C 这是代码片段 public class FooBar public FooBar string s constructor 1 some functionality public FooBar int i
  • C# 数据表更新多行

    我如何使用数据表进行多次更新 我找到了这个更新 1 行 http support microsoft com kb 307587 my code public void ExportCSV string SQLSyntax string L
  • 在 NaN 情况下 to_string() 可以返回什么

    我使用 VS 2012 遇到了非常令人恼火的行为 有时我的浮点数是 NaN auto dbgHelp std to string myFloat dbgHelp最终包含5008角色 你不能发明这个东西 其中大部分为0 最终结果是 0 INF
  • 为什么我的单选按钮不起作用?

    我正在 Visual C 2005 中开发 MFC 对话框应用程序 我的单选按钮是 m Small m Medium 和 m Large 它们都没有在我的 m Summary 编辑框中显示应有的内容 可能出什么问题了 这是我的代码 Pizz
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • 高效列出目录中的所有子目录

    请参阅迄今为止所采取的建议的编辑 我正在尝试使用 WinAPI 和 C 列出给定目录中的所有目录 文件夹 现在我的算法又慢又低效 使用 FindFirstFileEx 打开我正在搜索的文件夹 然后我查看目录中的每个文件 使用 FindNex
  • 等待 IAsyncResult 函数直至完成

    我需要创建等待 IAsyncResult 方法完成的机制 我怎样才能做到这一点 IAsyncResult result contactGroupServices BeginDeleteContact contactToRemove Uri
  • 打印大型 WPF 用户控件

    我有一个巨大的数据 我想使用 WPF 打印 我发现WPF提供了一个PrintDialog PrintVisual用于打印派生的任何 WPF 控件的方法Visual class PrintVisual只会打印一页 因此我需要缩放控件以适合页面
  • WebBrowser.Print() 等待完成。 。网

    我在 VB NET 中使用 WebBrowser 控件并调用 Print 方法 我正在使用 PDF 打印机进行打印 当调用 Print 时 它不会立即启动 它会等到完成整个子或块的运行代码 我需要确保我正在打印的文件也完整并继续处理该文件
  • 这个可变参数模板示例有什么问题?

    基类是 include
  • 为boost python编译的.so找不到模块

    我正在尝试将 C 代码包装到 python 中 只需一个类即可导出两个函数 我编译为map so 当我尝试时import map得到像噪音一样的错误 Traceback most recent call last File

随机推荐