[英]Trouble with implicit user-defined conversions
I have two classes: CoolEnum
, which is an attempt to turn enum class
into a real class with methods; 我有两个类:
CoolEnum
,它试图通过方法将enum class
变成真实的类; template <class WrapMe> class Wrapper;
, which is implicitly convertible to const WrapMe&
,可以隐式转换为
const WrapMe&
I've come up with the following implementation: 我提出了以下实现:
#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;
}
I surely can just static_cast
Wrapper<CoolEnum>
to CoolEnum
, but I believe that it might be possible to fix CoolEnum
class and avoid it. 我当然可以只
static_cast
Wrapper<CoolEnum>
到CoolEnum
,但是我相信可以修复CoolEnum
类并避免它。
One of the solutions I know of is to remove operator Impl
from CoolEnum
, and I guess its because it results in ambiguity (though I don't fully understand why). 我知道的解决方案之一是从
CoolEnum
删除operator Impl
,我猜是因为这会导致歧义(尽管我不完全理解为什么)。 To elaborate, I believe there are several possibilities for operator ==
: 详细地说,我相信
operator ==
有几种可能性:
convert Wrapper
to CoolEnum
and compare 将
Wrapper
转换为CoolEnum
并进行比较
convert Wrapper
to Impl
and compare 将
Wrapper
转换为Impl
并进行比较
... (maybe others) ...(也许是其他人)
but it seems like it should trivially be allowed -- all of them are compiler-generated, and lead to the same result 但是似乎应该允许它-所有这些都是编译器生成的,并导致相同的结果
I have two questions: 我有两个问题:
Why exactly do I get a compilation error? 为什么我确切会出现编译错误?
What is the best possible fix for CoolEnum
class? CoolEnum
类的最佳解决方案是CoolEnum
?
Thanks! 谢谢!
Why exactly do I get a compilation error?
为什么我确切会出现编译错误?
You are only allowed one user defined conversion in a conversion sequence. 您只能在转换顺序中进行一个用户定义的转换。 When you do
当你做
CoolEnum(CoolEnum::kFirst) == Wrapper<CoolEnum>(CoolEnum(CoolEnum::kFirst)
CoolEnum(CoolEnum::kFirst)
can be converted to a CoolEnum::Impl
in a single step but Wrapper<CoolEnum>(CoolEnum(CoolEnum::kFirst)
first has to convert the Wrapper
to a CoolEnum
, and then convert that to a CoolEnum::Impl
. Since that is two user defined conversions you get an error CoolEnum(CoolEnum::kFirst)
可以一步转换为CoolEnum::Impl
,但是Wrapper<CoolEnum>(CoolEnum(CoolEnum::kFirst)
首先必须将Wrapper
转换为CoolEnum
,然后再将其转换为CoolEnum::Impl
,因为这是两个用户定义的转换,所以会出现错误
What is the best possible fix for CoolEnum class?
CoolEnum类的最佳解决方案是什么?
Just add a operator ==
for it. 只需为其添加一个
operator ==
。 You can then do the comparison of the enum value in there. 然后,您可以在那里进行枚举值的比较。 This will work because it only take a single user defined conversion to go from a
Wrapper<T>
to T
. 这将起作用,因为仅需一次用户定义的转换即可将
Wrapper<T>
为T
Changing the code to 将代码更改为
#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;
}
lets it compile 让它编译
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.