我有两个类:CoolEnum
,这是尝试将enum class
变成带有方法的真实类; template <class WrapMe> class Wrapper;
,可以隐式转换为const WrapMe&
我想出了以下实现:
#include <cassert>
class CoolEnum {
public:
enum Impl {
kFirst, kSecond
};
explicit CoolEnum(Impl value) : value_(value) {
}
operator Impl() const {
return value_;
}
CoolEnum Inverse() const {
switch (value_) {
case kFirst:
return CoolEnum{kSecond};
default:
return CoolEnum{kFirst};
}
}
private:
Impl value_;
};
template <class WrapMe>
class Wrapper {
public:
Wrapper(WrapMe value, char other_info)
: value_(value), other_info_(other_info) {
}
operator const WrapMe&() const {
return value_;
}
private:
WrapMe value_;
char other_info_;
};
int main() {
// compiles
assert(CoolEnum(CoolEnum::kFirst) == CoolEnum::kFirst);
// does not compile: no match for operator ==
assert(CoolEnum(CoolEnum::kFirst)
== Wrapper<CoolEnum>(CoolEnum(CoolEnum::kFirst), 'e'));
return 0;
}
我当然可以将static_cast
Wrapper<CoolEnum>
改成CoolEnum
,但我相信可以修复CoolEnum
类并避免使用它。
我知道的一种解决方案是从operator Impl
中删除CoolEnum
,我猜想是因为这会导致歧义(尽管我不完全理解为什么)。详细地说,我相信operator ==
有几种可能性:
将Wrapper
转换为CoolEnum
并进行比较
将Wrapper
转换为Impl
并进行比较
...(可能是其他人)
但似乎应该简单地允许它-所有这些都是编译器生成的,并导致相同的结果
我有两个问题:
为什么我会出现编译错误?
CoolEnum
类的最佳解决方案是什么?
谢谢!
答案 0 :(得分:2)
为什么我会出现编译错误?
在转换序列中只允许您进行一个用户定义的转换。当你做
CoolEnum(CoolEnum::kFirst) == Wrapper<CoolEnum>(CoolEnum(CoolEnum::kFirst)
CoolEnum(CoolEnum::kFirst)
可以一步转换为CoolEnum::Impl
,但是Wrapper<CoolEnum>(CoolEnum(CoolEnum::kFirst)
首先必须将Wrapper
转换为CoolEnum
,然后将其转换到CoolEnum::Impl
。由于这是两个用户定义的转换,因此会出现错误
CoolEnum类的最佳解决方案是什么?
只需为其添加一个operator ==
。然后,您可以在那里进行枚举值的比较。这将起作用,因为仅需一次用户定义的转换即可从Wrapper<T>
转换为T
。将代码更改为
#include <cassert>
class CoolEnum {
public:
enum Impl {
kFirst, kSecond
};
explicit CoolEnum(Impl value) : value_(value) {
}
operator Impl() const {
return value_;
}
CoolEnum Inverse() const {
switch (value_) {
case kFirst:
return CoolEnum{kSecond};
default:
return CoolEnum{kFirst};
}
}
friend bool operator ==(const CoolEnum& lhs, const CoolEnum& rhs);
// ^^^^^^^^^^^^^^^^^ added this ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
private:
Impl value_;
};
bool operator ==(const CoolEnum& lhs, const CoolEnum& rhs)
{
return lhs.value_ == rhs.value_;
}
// ^^^^^^^^^^^^^^^^^ added this ^^^^^^^^^^^^^^^^^^^^^^^^^^
template <class WrapMe>
class Wrapper {
public:
Wrapper(WrapMe value, char other_info)
: value_(value), other_info_(other_info) {
}
operator const WrapMe&() const {
return value_;
}
private:
WrapMe value_;
char other_info_;
};
int main() {
// compiles
assert(CoolEnum(CoolEnum::kFirst) == CoolEnum::kFirst);
// does not compile: no match for operator ==
assert(CoolEnum(CoolEnum::kFirst)
== Wrapper<CoolEnum>(CoolEnum(CoolEnum::kFirst), 'e'));
return 0;
}
让其编译