如何只允许一组预定义的常量值?

时间:2015-03-24 23:44:05

标签: c++ class typedef

我有color类模板,上面有一些typedef,还有一堆颜色常量:

template<typename T>
class color
{
public:
    color(T data) : data(data) {}
    // other functions...
private:
    T data;
};
typedef color<uint16_t> color16;
typedef color<uint32_t> color32;

typedef color16 guicolor;
const guicolor WHITE = 0xFFFF;
const guicolor BLACK = 0x000F;
// other colors...

我还有一些 应该采用预定义的guicolor常量之一的函数,例如:

void foo(guicolor Color) { ... }

但是,foo也接受color<uint16_t>类的其他实例而不仅仅是预定义的guicolor常量,这是不可取的,因为您应该只能使用预定义的一组颜色GUI使用。

我可以使guicolor成为color16的子类,但值得/良好实践,因为我不会向该类添加任何其他功能,只能将其用作名称以区别于其他color16个实例?还有其他解决方案吗?

1 个答案:

答案 0 :(得分:1)

虽然评论中的建议可能是一些可能的选择,但我知道另一个技巧。

我们可以将它定义为一个单独的类,而不是使用guicolor或子类化定义typedef,而不是使用3个技巧。

class guicolor
{
private:
    uint16_t data;

private:    // Trick 1: private constructor!
    guicolor(uint16_t data) : data(data) {}

public:     // Trick 2: custom conversion!
    operator color16() const
    {
        return color16(this->data);
    }

public:     // Trick 3: static members!
    static const guicolor White;
    static const guicolor Black;
};

// Static members need to be *declared* in the class, and *defined* outside.
const guicolor guicolor::White = 0xFFFF;
const guicolor guicolor::Black = 0x0000;

然后,foo函数就是你所写的。

void foo(guicolor c) { ... }

接下来是用法。

color16 some_color_1 = 0xF000;  // Normal
color16 some_color_2 = guicolor::White; // guicolor object is implicitly convertible to color16

guicolor some_guicolor_1 = 0x1234;  // Compilation error as expected, due to private constructor.
guicolor some_guicolor_2 = guicolor::White; // Compilation pass, due to the pre-defined static member and compiler generated public copy constructor.

foo(some_color_1);      // Compilation error as expected
foo(some_guicolor_2);   // Compilation pass