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 找到。
我 运行 在使用嵌套枚举的模板参数重载朋友按位运算符时遇到问题。
最初我 运行 关注专有嵌入式 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 找到。