C ++使成员对象无名

时间:2018-02-21 22:17:58

标签: c++ member anonymous

我想编写一个方便的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;

这将是一种非常方便的使用颜色的方法,但是我想不出任何解决这个问题的方法。 最后,也许我对此有错误的方法,也许这可以用更少的努力来完成,但是我不能考虑任何其他不涉及大量模板类专业化的方法。

2 个答案:

答案 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