以下代码为整数创建Base类包装器。它提供了一个方法value()来获取和设置它的值,以及一个用户定义的转换和一个赋值运算符,以方便使用。
派生类是一个模板(旨在与枚举一起使用),它继承Base类包装器,它隐藏Base类的value(),用户定义转换和赋值运算符,并将它们替换为专门用于它的版本。提供的模板参数(枚举)。
class Base
{
public:
Base( int e ) : e_(e) {}
inline const int& value() const { return e_; }
inline void value( int e ) { e_ = e; }
inline operator const int& () const { return value(); }
inline Base& operator= ( int e ) { value( e ); return *this; }
protected:
int e_;
};
template< typename E >
class Enum : public Base
{
using Base::value;
using Base::operator const int&;
using Base::operator=;
public:
Enum( E e ) : Base( e ) {}
inline E value() const { return static_cast<E>( Base::value() ); }
inline void value( E e ) { Base::value( e ); }
inline operator E () const { return static_cast<E>( Base::value() ); }
inline Enum<E>& operator= ( E e ) { Base::value( e ); return *this; }
};
enum foo_t {
FOO_A,
FOO_B,
FOO_C
};
typedef Enum<foo_t> Foo;
现在让我们像这样调用这个代码:
Foo e( FOO_A );
e = FOO_B; // Ok!
foo_t b = e; // Ok!
// Why is this not ok?
if ( e ) {
printf("error C2451!");
}
if ( e.value() ) { // Ok!
e = FOO_C;
}
// Why is this not ok?
switch ( e ) {
default:
printf("error C2450!");
}
switch ( e.value() ) { // Ok!
default:
e = FOO_A;
}
为什么if和switch语句在我明确隐藏基类'用户定义转换(而且if和switch语句不可访问)时无法编译(Ambiguous user-defined-conversion
)。同样含糊不清的e.value()
函数不会遇到这个问题。
1>test.cpp(60): error C2451: conditional expression of type 'Foo' is illegal
1> Ambiguous user-defined-conversion
1>test.cpp(69): error C2450: switch expression of type 'Foo' is illegal
1> Ambiguous user-defined-conversion
答案 0 :(得分:1)
ref#1和ref#2(我似乎无法找到标准实际说这个,只有人引用它......)
似乎C ++标准有关于条件的说法:
条件应为整数类型,枚举类型或类型,其中存在单个非显式转换函数为整数或枚举类型(12.3)。如果条件是类类型,则通过调用该转换函数来转换条件,并使用转换结果代替本节其余部分的原始条件。进行整体促销。
由于有2个用户定义的转换“可用”,即使只有1个可以访问,标准也说不行。
答案 1 :(得分:-1)
(using
中的这些Enum
陈述是什么?我不知道他们做了什么。)
我不确定错误发生的原因,但您可以通过向if
添加类似的内容来解决Base
语句的问题:
inline operator bool () const { return e_ != 0; }
至于switch
,我从来没有见过任何东西,只允许整数类型(Foo
不是),我怀疑编译器是否足够聪明,试图找到转换为枚举运算符本身。无论如何我总是打电话给value()
。