C++ 隐式转换未按预期工作
我已经编写了一个简单的C++ 隐式转换未按预期工作,c++,c++11,implicit-conversion,C++,C++11,Implicit Conversion,我已经编写了一个简单的Flags类,但是我的操作符定义有一个问题。我似乎依赖于一些不存在的隐式转换规则 enum class SomeEnum { ONE, TWO, THREE }; template<typename Enum> class Flags { Flags(const Flags& f) { }; Flags(Enum e) { }; Flags& operator |=(Flags<Enum> f) {
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;
}
但是错误仍然是一样的()。为了知道
SomeEnum
可以转换为Flags
,它必须已经将Enum
模板参数推导为SomeEnum
,但是它无法从参数中推断,因为它们都不匹配Flags
i、 e.在检查转换为其他类型之前,必须先进行模板参数推导
您可以调整函数,以便只有一个参数参与参数推导:
template<typename T> struct nondeduced { using type = T; }
template<typename Enum>
Flags<Enum> operator |(Enum a, Flags<typename nondeduced<Enum>::type> b)
然后您可以说SomeEnum::TWO | flags(SomeEnum::TWO)
,这避免了歧义
作为一个风格点,.可能的重复我不确定它是否完全重复(希望其他人也看到它),但相关的:我不知道到底要搜索什么,因为谷歌搜索
隐式转换没有按预期工作
没有给出任何好的结果(显然)@阿尔及德·阿斯佩雷斯:我看不出这个问题有任何共同之处。他在标志
类(甚至没有模板化;他使用了运算符|对a和b具有相同类型)方面还有另一个问题@nyronium,从您得到的错误判断,您的模板化类甚至没有受到质疑。这个错误是由于编译器没有为运算符|
找到合适的匹配项,其中两个操作数都是SomeEnum
类型,因此-我的建议。有没有办法对其中一个不明确的重载进行优先级排序?因为Flags
是库的一部分,我现在必须创建template operator |(Enum a,Enum b)
,这可能会破坏其他不应该用作标志的枚举。@nyronium对我来说听起来像是一个灾难,让a | b
根据微妙的上下文做一些不同的事情change@M.M很可能。。。虽然这不是一个理论问题,只是一个C++的问题。也许有一天。@M.M事实上,如果我只对两个操作符中的一个应用这个解决方案,我就会有这种行为。如果存在用户定义的运算符Enum | Enum,则它优先,并且在任何情况下都没有歧义。@jonathan wakely,为了完整性,您是否介意详细说明此方法?
friend Flags operator |(Enum a, Flags b) { return b | a; }
friend Flags operator |(Flags a, Enum b) { return a |= b; }
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);
template<typename Enum>
inline Flags<Enum> flags(Enum e) { return Flags<Enum>(e); }