混合常数和"动态"期权价值

时间:2014-04-15 22:18:23

标签: c++

我有一个值可以采用以下语义值之一(它们不具有上下文的意义,但确切的上下文并不重要):

  • 仅限请求
  • 仅限活动
  • 自动使用间隔 N (其中 N 是1到200之间的整数)

在内部,所有这些都由一个整数表示:

  • 仅按要求= 0
  • 仅限活动= 252
  • 自动使用间隔 N = N (其中 N 从1到200)

我想用名为MessageType的类型表示此值,并且我想将此值传递给函数setMessageType(),并将它们作为类的成员:

class Example {
public:
   // <= definition of MessageType would be here. 
   ...
   void setMessageType (int id, MessageType type);
};

我希望此类型符合以下要求:

  • 使用它很明显(例如,名为ByRequestOnlyOnEventOnly的常量。)
  • &#34;自动使用间隔&#34;很清楚强制 N 在运行时处于适当的范围(例如Automatic(50))。
  • 使用此类型的开发人员不会无意中传递非预期的价值(奇怪的演员阵容)是至关重要的;也就是说,我希望enum提供相同级别的编译时语义,除了&#34;自动&#34;的运行时验证。价值范围。
  • &#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;某些值的范围与运行时检查这些情况?

2 个答案:

答案 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);