C++ 友元运算符使用嵌套枚举的模板参数重载

C++ friend operator overloading with template parameters for nested enums

我 运行 在使用嵌套枚举的模板参数重载朋友按位运算符时遇到问题。

最初我 运行 关注专有嵌入式 C++ 编译器的问题。之后我尝试了 gcc、clang 和 MSVC 并得到了完全相同的失败。除了,我尝试过的任何 5.0 之前的 GCC 版本都能够编译示例代码。使用任何编译器选择 C++ 标准似乎没有任何区别。

这是一个 example:

struct Complex
{
   struct Nested1
   {
       enum ENUM
       {
          Value1_1,
          Value1_2
       };
   };

   struct Nested2
   {
       enum ENUM
       {
          Value2_1,
          Value2_2
       };
   };

   template<typename EnumL, typename EnumR>
   friend Complex operator|(const EnumL dummyL, const EnumR dummyR)
   {
        Complex dummyComplex;
        return dummyComplex;
   }
};

int main()
{
   Complex complex = Complex::Nested1::Value1_1 | Complex::Nested2::Value2_2;
}

编译器没有看到 运算符 |。如果我将运算符重载移动到结构定义下方,代码就会编译。虽然现在已经不是友元函数了

但是,稍有不同的代码 example 编译时没有任何问题。

struct Complex
{
    enum ENUM1
    {
        Value1_1,
        Value1_2
    };

    enum ENUM2
    {
        Value2_1,
        Value2_2
    };

    template<typename EnumL, typename EnumR>
    friend Complex operator|(const EnumL dummyL, const EnumR dummyR)
    {
        Complex dummyComplex;
        return dummyComplex;
    }
};

int main()
{
   Complex complex = Complex::Value1_1 | Complex::Value2_2;
}

我在这里错过了什么?

原因是在第一个例子中 operator| 不在定义枚举类型的 class 中。因此,ADL 未找到该函数(请参阅该页第二个列表的第 4 点):

For arguments of enumeration type, the innermost enclosing namespace of the declaration of the enumeration type is defined is added to the set. If the enumeration type is a member of a class, that class is added to the set.

在上面的引用中,“set”被定义为“关联的命名空间集和 classes”,用于查找函数。

因此在第一个示例中没有找到 operator| 类型 returns 和 Complex 类型。

当您在第一个示例中将 operator| 重载移动到 Complex class 之外时,您将其移动到全局命名空间中。全局命名空间始终是上述“集合”的一部分,因此发现了重载。

在第二个示例中,枚举和 operator| 函数在同一个 class 中,因此它们可以被 ADL 找到。