我目前正在玩模板来构建颜色类。我正在使用模板,因为可以使用不同的color spaces或color models来定义和存储颜色。
基本上,我想出了一个类,它将颜色模型类作为模板参数并从中继承,以便访问特定于模型的方法red()
,green()
和{{1对于RGB模型,或blue()
,hue()
和saturation()
用于HSV模型。我还为颜色和模型转换器函数编写了一些模型类以及一些方便的typedef。
value()
这一开始似乎是一个好主意。然而,出现了多个问题,首先是整个事情看起来很丑陋而且注定要失败。
事实上,我有两个主要问题,第一是如下:如何制作模特&#39;方法返回颜色而不是模型(他们自己的类型)?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] 为了创建一个新的颜色模型,人们不应该(并且根本不应该)修改任何现有的类(模型或颜色类),但可能想要编写相应的转换器。 [编辑]
所以我的问题是:我的设计是否可以修复,基本上是一个好的设计(修复后)?如果没有,为了获得与我指定的功能相同的功能,我的可能性是什么?
答案 0 :(得分:1)
这种设计背后的想法是能够创建新的颜色模型,使用适当的转换器与现有颜色模型相比较,并将它们与Color类(具有模型类型的typedef和一般转换构造函数)一起使用。
这应该可以使用模板专业化。您可以为每个不同的颜色模型组合实现一个实例,或者实现一个通用模型,并在每个其他颜色模式中为此设置一个私有转换器。
答案 1 :(得分:1)
您的一条评论:
没有代码不应该关心使用的模型。
我认为这是问题的主旨。
如果没有与模型无关的Color
客户端代码,那么模板和面向对象都没有意义。
你基本上创建了两个完全独立的类,它们的名字恰好有尖括号。只需创建两个完全独立的非模板类RgbColor
和HsvColor
。它应该使您的整个代码更清晰。
主要的好处是有一个转换器构造函数而不是 函数,如果添加新模型,则无需修改现有模型(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>)
类型的哪个函数?