为模板类提供多个可供选择的模型
Providing multiple models for a template class to choose from
我目前正在使用模板来构建一个颜色类。我之所以使用模板,是因为可以使用不同的颜色空间或颜色模型来定义和存储颜色。
所以基本上,我想出了一个类,它将颜色模型类作为模板参数并从中继承,以便访问特定于模型的方法,如RGB模型的red()
, green()
和blue()
,或HSV模型的hue()
, saturation()
和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;
另一个问题在于不同型号的颜色之间的转换:
template <typename U>
explicit Color(const Color<U>& c);
我最初计划在这个构造函数中使用模型转换函数,但我无法设置它。
这种设计背后的思想是能够创建新的颜色模型,并使用与现有颜色模型之间的适当转换器,并将它们与color类一起使用(该类具有模型类型的typedef和通用转换构造函数)。[edit]为了创建新的颜色模型,不需要(也不应该)修改任何现有的类(模型或颜色类),但可能需要编写相应的转换器。[编辑]
所以我的问题是:我的设计是否有可能修复,基本上,一个好的设计(修复后)?如果没有,我该怎么做才能拥有与我指定的相同的功能呢?
从你的一个评论:
没有代码不应该关心所使用的模型。
我想这就是问题的关键所在。
如果没有模型独立的Color
客户端代码,那么模板和面向对象都没有意义。
你基本上已经创建了两个完全独立的类,碰巧它们的名字中有尖括号。只需创建两个完全独立的非模板类RgbColor
和HsvColor
。这会使你的整个代码更清晰。
的主要好处是有一个转换构造函数,而不是函数,如果添加新模型,则无需修改现有模型添加转换器).
我不认为这会带来任何真正的好处,因为您仍然需要显式地实现从模型X到模型y的每一次转换。在任何情况下都没有真正的自动化。
更简洁的解决方案是编写非成员非友元转换函数:RgbColor ToRgb(HsvColor const &color);
HsvColor ToHsv(RgbColor const &color);
Non-member - non-friend表示如果添加了新模型,不需要更改任何类。这进一步意味着所有的转换在客户端代码中都是清晰可见的,并且不太可能发生意外的不需要的转换。
另一个优点是支持单向转换。例如,您以后可能需要一个不支持alpha的RGB颜色类。RgbColorNoAlpha
的实例应该转换为RgbColor
,反之则不行。通过RgbColorNoAlpha ToRgbColorNoAlpha(RgbColor const &color)
的缺失,代码可以轻松地满足这一要求。
这种设计背后的思想是能够创建新的颜色模型,并使用与现有模型之间的适当转换器,并将它们与color类一起使用(该类具有模型类型的typedef和通用转换构造函数)。
这应该可以通过模板专门化实现。您可以为每个不同的颜色模型组合实现一个实例,或者实现一个通用模型,并在每个其他颜色模型中为其提供一个私有转换器。
考虑这种可能性:
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之间没有公共接口,因此将它们作为共同祖先的子意义不大。
如果在各种颜色的实现中没有共同的成员,你可以写哪种fn(color<M>)
类型的函数?
- 如何使用默认参数等选择模板专业化
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 选择要调用的构造函数
- C++选择排序算法中的逻辑错误
- QTreeView幻灯片多选后无法使用单击选择
- 无法获取菜单选择以运行函数.C++
- QTableView:endMoveRows在模型中重置水平页眉大小
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 将IBM Rhapsody模型集成到VS 2019中
- 在C++中,如何通过几种类型从元组中选择多个元素
- 旋转模型矩阵时的形状失真
- 讨论 - 创建矩阵时的数组与向量的向量 - 什么是最实用的选择
- 对可变参数使用声明.如何选择正确的功能
- 选择选举获胜者的程序
- 成员函数调用和C++对象模型
- 如何选择在 csv 文件中输出的位置
- 正确复制 QTableView 中的选择(模型索引问题)
- 是否可以从代理访问QTreeview的选择模型
- 为模板类提供多个可供选择的模型
- QListView的默认选择模型的所有权