我想编写一个方便的Color管理类,这将允许我使用不同的组件顺序和基本上不同的设置。我希望它在编译时可以区分。 假设我有这段代码:
template <typename _valueType>
struct RGBAColorData {
using ValueType = _valueType;
union {
struct { ValueType r, g, b, a; };
ValueType components[4];
};
};
这个(即使匿名结构是非标准的)工作正常,当我想这样使用它时:
RGBAColorData color;
color.r = whatever;
但是,这不是我的代码的最终形式。我希望它拥有“拥有”类模板,在编译时可以在XYZColorData
之间进行选择。让我们说它看起来像这样:
template <typename _valueType, template <typename> _dataScheme>
struct Color
{
using ValueType = _valueType;
using DataScheme = _dataScheme<ValueType>;
// what now?
// DataScheme data; // ???
};
这会产生问题,因为我希望我的代码可以这样使用:
using RGBAColorF = Color<float, RGBAColorData>;
RGBAColorF brushColor;
brushColor.r = whatever;
这将是一种非常方便的使用颜色的方法,但是我想不出任何解决这个问题的方法。 最后,也许我对此有错误的方法,也许这可以用更少的努力来完成,但是我不能考虑任何其他不涉及大量模板类专业化的方法。
答案 0 :(得分:1)
为获得一些好的句法效果而四处寻找是充满危险的,可能会抹杀未来的进化。
首先,在C ++中,只有一个联盟成员可以随时处于活动状态。所以切换数组和结构的使用不能保证工作,即使在许多编译器上,这可能会导致预期的结果。
然后,不能保证结构成员是连续的,因此如果混合使用数组和结构将起作用,它可能仍然不会导致正确的结果,即使在许多编译器上这将按预期工作。 / p>
如果您仍想混合使用特定颜色成分r,g,b和阵列,您应该考虑采用更安全的方法:
template <typename _valueType>
struct RGBAColorData {
using ValueType = _valueType;
ValueType components[4];
ValueType &r=components[0], &g=components[1],
&b=components[2], &a=components[3]; // ATTENTION (see explanations)
};
注意:我快速而且肮脏。您应该使用适当的构造函数,复制构造函数和赋值运算符来更好地实现三的规则,以确保引用不会搞砸。
我不太喜欢这个解决方案,但它安全地工作(online demo):诀窍是使r,g,b,对特定数组项的引用。然后,您确定可以混合访问方式,并且您完全确定两者之间的映射是正确的。
您的初始方法和我的解决方法的问题是它们打破了封装:您必须知道颜色的内部结构才能使用它。
通过这种方法,你永远无法进化。例如,切换到CMYK颜色方案,或采用位字段编码将受到损害。
正确的方法是拥有一套吸气剂和固定剂,以完全隐藏内部结构与外部世界。当然,在语法上它看起来并不那么好,但是你真的能够编写真正的通用颜色代码,其中编码方案可以是编译时策略。
答案 1 :(得分:0)
最后,我决定使用继承(正如Ben Voigt所说)。
我使用这个答案提出的出色方法修复了另一个问题,即使代码不安全的工会:
https://stackoverflow.com/a/494760/4386320