为什么将 int 分配给枚举类型在 OpenCV _InputArray::kind() 中有效?

Why is assigning an int to enum type valid in OpenCV _InputArray::kind()?

我认为在 C++ 中向枚举变量赋值和 int 值是无效的,并且已经有验证这一点的问题,例如 .

但是我只看到下面的代码没有导致编译错误:

// https://github.com/opencv/opencv/blob/4.x/modules/core/include/opencv2/core/mat.hpp#L158-L265
class CV_EXPORTS _InputArray
{
public:
    enum KindFlag {  //!! KindFlag is an enum type
        KIND_SHIFT = 16,
        FIXED_TYPE = 0x8000 << KIND_SHIFT,
        FIXED_SIZE = 0x4000 << KIND_SHIFT,
        KIND_MASK = 31 << KIND_SHIFT,

        ...
    }
    
    ...
};


// https://github.com/opencv/opencv/blob/4.x/modules/core/src/matrix_wrap.cpp#L370-L378
_InputArray::KindFlag _InputArray::kind() const
{
    KindFlag k = flags & KIND_MASK;  //!! this line, I think it is assign enum type var `k` with int value `flag & KIND_MASK`, but it it not cause compile error
#if CV_VERSION_MAJOR < 5
    CV_DbgAssert(k != EXPR);
    CV_DbgAssert(k != STD_ARRAY);
#endif
    return k;
}

我尝试用下面的代码实现一个最小的InputArray_ class,这会导致编译错误,使用与上面相同的assigne,这让我很困惑:

// what.cpp
class InputArray_
{
public:
    enum KindFlag {
        KIND_SHIFT = 16,
        KIND_MASK = 31 << KIND_SHIFT,

        NONE = 0 << KIND_SHIFT,
        MAT  = 1 << KIND_SHIFT
    };

    bool empty() const;
    InputArray_::KindFlag kind() const;

public:
    InputArray_();

protected:
    int flags;
    void* obj;
};


InputArray_::KindFlag InputArray_::kind() const
{
    KindFlag k = flags & KIND_MASK; //!! now this cause compile error
    return k;
}

int main()
{

}

编译器为AppleClang 13.0.0,完整错误信息为:

what.cpp:26:14: error: cannot initialize a variable of type 'InputArray_::KindFlag' with an rvalue of type 'int'
    KindFlag k = flags & KIND_MASK;
             ^   ~~~~~~~~~~~~~~~~~
1 error generated.

有谁知道为什么OpenCV的不会导致编译错误?

opencv 定义运算符 & 本身,因此它不再导致 int

您可以在您链接的部分下方看到它

__CV_ENUM_FLAGS_BITWISE_AND(_InputArray::KindFlag, int, _InputArray::KindFlag)

link


宏的实现

#define __CV_ENUM_FLAGS_BITWISE_AND(EnumType, Arg1Type, Arg2Type)                                     \
static inline EnumType operator&(const Arg1Type& a, const Arg2Type& b)                                \
{                                                                                                     \
    typedef std::underlying_type<EnumType>::type UnderlyingType;                                      \
    return static_cast<EnumType>(static_cast<UnderlyingType>(a) & static_cast<UnderlyingType>(b));    \
}                                                                                                    

link