我有一个值可以采用以下语义值之一(它们不具有上下文的意义,但确切的上下文并不重要):
在内部,所有这些都由一个整数表示:
我想用名为MessageType
的类型表示此值,并且我想将此值传递给函数setMessageType()
,并将它们作为类的成员:
class Example {
public:
// <= definition of MessageType would be here.
...
void setMessageType (int id, MessageType type);
};
我希望此类型符合以下要求:
ByRequestOnly
和OnEventOnly
的常量。)Automatic(50)
)。enum
提供相同级别的编译时语义,除了&#34;自动&#34;的运行时验证。价值范围。int
。换句话说,我希望能够编写看起来像这样的代码:
Example example;
example.setMessageType(0, Example::ByRequestOnly);
example.setMessageType(0, Example::OnEventOnly);
example.setMessageType(0, Example::Automatic(1));
example.setMessageType(0, Example::Automatic(200));
int n = ...; // from 1 to 200
example.setMessageType(0, Example::Automatic(n));
example.setMessageType(0, Example::Automatic(500)); // <= throws exception
在setMessageType()
中,我需要将值转换为其内部表示形式:
void Example::setMessageType (int id, MessageType type) {
int internal = type.internalValue(); // e.g. 252 for OnEventOnly
...
}
我很难定义满足所有上述要求的类型。一种可能性是使用等于内部表示的整数类型:
class Example {
public:
typedef int MessageType;
static const int ByRequestOnly = 0;
static const int OnEventOnly = 252;
// use integer value 1-200 for interval
};
问题:任何int
都可以在没有语义的情况下使用。没有验证自动间隔设置完成。
我也尝试使用struct
混合常量值和静态函数:
class Example {
public:
struct MessageType {
friend class Example;
private:
explicit MessageType (int iv) : internalValue_(iv) { }
int internalValue_;
};
static const MessageType ByRequestOnly = MessageType(0);
static const MessageType OnEventOnly = MessageType(252);
static MessageType Automatic (int interval) {
if (interval >= 1 && interval <= 200)
return MessageType(interval);
else
throw runtime_error("Invalid automatic interval.");
}
};
问题:这不能编译,因为构造函数不能用在常量表达式中。
我能做的另一件事是使用一个巨大的枚举:
class Example {
public:
enum MessageType {
ByRequestOnly = 0,
OnEventOnly = 252,
Automatic_1 = 1,
Automatic_2 = 2,
Automatic_3 = 3,
...,
Automatic_200 = 200
};
};
但这非常麻烦,无论是实施,还是特别是将int
转换为其中一个值为&#34;自动&#34; (运行时检查自动值将在从int到枚举的转换实现中完成。)
我该怎么做?我如何定义一些类型,它给我enum
类似的编译时行为,但也允许一个&#34;动态&#34;某些值的范围与运行时检查这些情况?
答案 0 :(得分:2)
我的想法是不要使你的Example
类型的常量。你甚至可以让它们成为不同的类型。
struct Example {
static const RequestType {} ByRequestOnly;
static const EventType {} OnEventOnly;
struct Automatic {
explicit Automatic(int v)
:value(v)
{
if(value<1 || value>200)
throw std::runtime_error("Invalid automatic interval.");
}
private:
friend Example;
int value;
};
void setMessageType (int id, RequestType type) {internal = 0;}
void setMessageType (int id, EventType type) {internal = 252;}
void setMessageType (int id, Automatic type) {internal = type.value;}
private:
int internal;
};
答案 1 :(得分:2)
如果将静态常量的初始化放在源文件中而不是标题中,则会编译Example
类。
class Example {
public:
struct MessageType {
friend class Example;
private:
explicit MessageType (int iv) : internalValue_(iv) { }
int internalValue_;
};
static const MessageType ByRequestOnly;
static const MessageType OnEventOnly;
static MessageType Automatic (int interval) {
if (interval >= 1 && interval <= 200)
return MessageType(interval);
else
throw runtime_error("Invalid automatic interval.");
}
};
cpp文件中的其他地方
const Example::MessageType Example::ByRequestOnly = Example::MessageType(0);
const Example::MessageType Example::OnEventOnly = Example::MessageType(252);