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); }