为模板类提供多种模型供您选择

时间:2014-08-10 14:17:29

标签: c++ templates inheritance c++11

我目前正在玩模板来构建颜色类。我正在使用模板,因为可以使用不同的color spacescolor models来定义和存储颜色。

基本上,我想出了一个类,它将颜色模型类作为模板参数并从中继承,以便访问特定于模型的方法red()green()和{{1对于RGB模型,或blue()hue()saturation()用于HSV模型。我还为颜色和模型转换器函数编写了一些模型类以及一些方便的typedef。

value()

这一开始似乎是一个好主意。然而,出现了多个问题,首先是整个事情看起来很丑陋而且注定要失败。

事实上,我有两个主要问题,第一是如下:如何制作模特'方法返回颜色而不是模型(他们自己的类型)?

template <typename T>
class Color : public T {
public:
    typedef T Model;

    using T::T;

    // This is meant to convert colors with different models
    template <typename U>
    explicit Color(const Color<U>& c);
};

class RGB {
public:
    static constexpr auto name = "RGB";

    RGB() = default;
    RGB(unsigned int argb);
    RGB(unsigned int r, unsigned int g, unsigned int b, unsigned int a = 0xFF);

    RGB lighter(double factor = 1.2) const;
    RGB negative() const;
    RGB greyscale() const;

    unsigned int argb() const;
    unsigned int red() const;
    unsigned int green() const;
    unsigned int blue() const;
    unsigned int alpha() const;

private:
    unsigned int m_argb;
};

class HSV {
public:
    static constexpr auto name = "HSV";

    HSV() = default;
    HSV(unsigned int h, unsigned int s, unsigned int v, unsigned int a = 0xFF);

    HSV lighter(double factor = 1.2) const;
    HSV complementary() const;
    HSV greyscale() const;

    unsigned int hue() const;
    unsigned int saturation() const;
    unsigned int value() const;
    unsigned int alpha() const;

private:
    unsigned int m_h, m_s, m_v, m_a;
};

typedef Color<RGB> RGBColor;
typedef Color<HSV> HSVColor;

template<typename From, typename To>
To ColorModelConverter(From model);
template<>
RGB ColorModelConverter<HSV, RGB>(HSV model);
template<>
HSV ColorModelConverter<RGB, HSV>(RGB model);

另一个问题在于使用不同模型的颜色之间的转换:

Color<RGB> greyscale() const;
// ... instead of ...
RGB greyscale() const;

我最初计划在此构造函数中使用模型转换器函数,但我无法设置它。

这种设计背后的想法是能够创建新的颜色模型,使用适当的转换器与现有颜色模型相比较,并将它们与Color类(具有模型类型的typedef和一般转换构造函数)一起使用。 [edit] 为了创建一个新的颜色模型,人们不应该(并且根本不应该)修改任何现有的类(模型或颜色类),但可能想要编写相应的转换器。 [编辑]

所以我的问题是:我的设计是否可以修复,基本上是一个好的设计(修复后)?如果没有,为了获得与我指定的功能相同的功能,我的可能性是什么?

3 个答案:

答案 0 :(得分:1)

  

这种设计背后的想法是能够创建新的颜色模型,使用适当的转换器与现有颜色模型相比较,并将它们与Color类(具有模型类型的typedef和一般转换构造函数)一起使用。

这应该可以使用模板专业化。您可以为每个不同的颜色模型组合实现一个实例,或者实现一个通用模型,并在每个其他颜色模式中为此设置一个私有转换器。

答案 1 :(得分:1)

您的一条评论:

  

没有代码不应该关心使用的模型。

我认为这是问题的主旨。

如果没有与模型无关的Color客户端代码,那么模板和面向对象都没有意义。

你基本上创建了两个完全独立的类,它们的名字恰好有尖括号。只需创建两个完全独立的非模板类RgbColorHsvColor。它应该使您的整个代码更清晰。

  

主要的好处是有一个转换器构造函数而不是   函数,如果添加新模型,则无需修改现有模型(to   添加转换器)。

我认为这不会带来任何实际好处,因为您仍然必须明确实现从模型X到模型Y的每次转换。在任何情况下都没有真正的自动化。< / p>

更清洁的解决方案是编写非成员非朋友转换函数:

RgbColor ToRgb(HsvColor const &color);
HsvColor ToHsv(RgbColor const &color);

非会员非朋友意味着如果添加新模型,则不得更改任何类。这进一步意味着所有转化都在客户端代码中清晰可见,并且不太可能发生意外的不需要的转换。

另一个优点是支持单向转换。例如,您可能稍后需要没有alpha支持的RGB颜色类。 RgbColorNoAlpha的实例应该可以转换为RgbColor,但反之亦然。通过RgbColorNoAlpha ToRgbColorNoAlpha(RgbColor const &color)缺席,代码可以轻松满足此要求。

答案 2 :(得分:0)

考虑这种可能性:

struct HSV; //undefined
struct RGB; //undefined

template<class M> class color; //undefined

template<>
class color<RGB>
{
  //specific RGB implementations
};

template<>
class color<HSV>
{
  //specific HSV implementation
};

但是到目前为止你的设计确实存在问题,RGC和HSV之间没有共同的接口,所以将它们作为共同祖先 child 几乎没有意义。< / p>

如果各种颜色实现中没有共同成员,您可以编写fn(color<M>)类型的哪个函数?