C++ 使用枚举进行标志和按位运算,很容易

loo*_*oop 0 c++ enums visual-studio-2010

在 CI 中能够采用两个或多个枚举标志并包含或它们: (flag1 | flag2)

在 C++ 中,我不能做同样的事情。我有一些标志,我已将其范围限定在我的班级,但我必须对它们进行 OR 转换。它看起来像这样:

namespace name
{
    class test
    {
    public:
        enum flag
        {
            firstflag = 1, secondflag = 2, thirdflag = 4
        };

        void foo(flag flags)
        {
            return;
        }
    };
}

int main(int argc, char *argv[])
{
    name::test obj;

    obj.foo((name::test::flag)(name::test::firstflag | name::test::secondflag));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在实际代码中,这比这个例子要多。我想知道是否有更好的方法。我可以更改传递给 int 的参数,void foo(int flags)但是在 Visual Studio 2010 调试器中,我看不到 ORed 标志,只有一个数字。


没有演员我得到一个错误:

obj.foo(name::test::firstflag | name::test::secondflag);
error C2664: 'name::test::foo' : cannot convert parameter 1 from 'int' to 'name::test::flag'
Run Code Online (Sandbox Code Playgroud)

我在stackoverflow上搜索并发现了一个问题,答案是重载|运算符:
c++ - “enum - invalid conversion from int” in class - 爱编程的大狗

然而,当我使用std::ios标志时,我不必进行任何转换,这是为什么呢?例如 fstream 有一个原型,例如fstream(char *filename, std::ios_base),我可以在我的代码中做到这一点:

fstream("filename",  ios::in | ios::out);
Run Code Online (Sandbox Code Playgroud)


你们有什么建议?我没有很多 C++11 功能,所以如果你能在回答时记住这一点。谢谢

小智 5

在 ios::in、ios::out 等的 GCC 实现中,它们使用运算符重载来获得所需的效果。例如

inline _GLIBCXX_CONSTEXPR _Ios_Openmode
operator|(_Ios_Openmode __a, _Ios_Openmode __b)
{ return _Ios_Openmode(static_cast<int>(__a) | static_cast<int>(__b)); }
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您可以定义以下方法:

inline flag operator|(flag f1, flag f2)
{ 
  return flag(static_cast<int>(f1) | static_cast<int>(f2)); 
}
Run Code Online (Sandbox Code Playgroud)

干杯,