隐式转换未按预期工作
implicit conversion not working as expected
我已经编写了一个简单的Flags
类,但我的运算符定义存在问题。我似乎依赖于某种不存在的隐式转换规则。
enum class SomeEnum { ONE, TWO, THREE };
template<typename Enum>
class Flags {
Flags(const Flags& f) { };
Flags(Enum e) { };
Flags& operator |=(Flags<Enum> f) {
//...;
return *this;
}
};
template<typename Enum>
Flags<Enum> operator |(Enum a, Flags<Enum> b) { return b | a; }
template<typename Enum>
Flags<Enum> operator |(Flags<Enum> a, Enum b) { return a |= b; }
int main() {
Flags<SomeEnum> flags = SomeEnum::ONE | SomeEnum::TWO;
return 0;
}
在编译时,我得到了这个错误:
implicit.cpp: In function ‘int main()’:
implicit.cpp:26:40: error: no match for ‘operator|’ (operand types are ‘SomeEnum’ and ‘SomeEnum’)
Flags<SomeEnum> flags = SomeEnum::ONE | SomeEnum::TWO;
我的理解是,其中一个SomeEnum
隐式转换为Flags<Enum>
,然后传递给正确的运算符。我缺少什么规则?
编辑:
我已经研究了https://stackoverflow.com/questions/9787593
,但所提出的解决方案(非成员友元运算符)并没有解决我的问题。我确实删除了全局定义并添加了以下成员:
friend Flags operator |(Enum a, Flags b) { return b | a; }
friend Flags operator |(Flags a, Enum b) { return a |= b; }
但错误仍然是一样的(现场演示)。
为了知道SomeEnum
可以转换为Flags<SomeEnum>
,它必须将Enum
模板参数推导为SomeEnum
,但它无法从参数中推导出来,因为它们都不匹配Flags<Enum>
。
即在可以检查到另一类型的转换之前必须进行模板参数推导。
您可以调整函数,使只有一个参数参与参数推导:
template<typename T> struct nondeduced { using type = T; }
template<typename Enum>
Flags<Enum> operator |(Enum a, Flags<typename nondeduced<Enum>::type> b)
或等效地:
template<typename E> struct FlagType { using type = Flags<E>; }
template<typename Enum>
Flags<Enum> operator |(Enum a, typename FlagType<Enum>::type b);
这在非推导上下文中使用Enum
模板参数,因此只有其他参数用于推导。
但在这样做之后,您现在有了不明确的重载,因为编译器无法知道您是希望转换第一个参数,还是希望转换第二个参数。
您需要添加一个重载,该重载采用两种SomeEnum
类型,并显式执行到Flags<SomeEnum>
的转换。如果枚举类型应该与operator|
一起使用,那么它应该定义该运算符本身。
另一个不涉及更改枚举类型的选项是添加一个助手,将枚举器转换为Flags
对象:
template<typename Enum>
inline Flags<Enum> flags(Enum e) { return Flags<Enum>(e); }
那么你可以说CCD_ 15,这样就避免了歧义。
从风格上讲,不要将ALL_CAPS用于枚举器。
相关文章:
- 如何定义在用作函数参数时工作的类模板的转换
- 将双精度值转换为 char 变量时字符串流如何工作
- 隐式转换是否应该在模板参数的上下文中工作?
- strcmp/char* 转换无法按预期工作
- 如何在 Poco 中将工作 HTTP 代码转换为 HTTPS
- Qt-工作线程崩溃时将cv::Mat转换为QImage
- 我的代码在作为参数传入 .begin() 时不起作用,但在我将 .begin() 转换为迭代器后工作
- 字符串文字到 char 数组的转换如何在C++中实际工作
- 将缓冲区转换为在现有程序中工作的iStream
- 更新MySQL连接器后,隐式转换停止工作
- 为什么Arduino(小端序)上的Sha1在没有转换为大端序的情况下工作?
- 如何使转换功能工作?
- 以下对二进制转换代码的小数如何工作
- 隐式转换未按预期工作
- 尝试将工作python程序转换为C++但不起作用
- 字符串到字符指针的转换如何在C++中工作
- 如何将负数转换为更广泛的类型在内部工作
- 十六进制、二进制和 oct 到 dec 转换器无法正常工作C++
- 使用模板无法按预期工作进行继承和强制转换
- 超级强大:实时音调转换,时间扩展器不工作