C ++使成员对象未命名

C++ make member object unnamed

我想编写方便的颜色管理 class,这将允许我使用不同顺序的组件和基本上不同的设置。我希望它在编译时是可区分的。 假设我有这段代码:

template <typename _valueType>
struct RGBAColorData {
    using ValueType = _valueType;
    union {
        struct { ValueType r, g, b, a; };
        ValueType components[4];
    };
};

这个(即使匿名结构是非标准的)工作正常,当我想这样使用它时:

RGBAColorData color;
color.r = whatever;

但是,这不是我的代码的最终形式。我希望它有 "owning" class 模板,在编译时 select 介于 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;

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

不要这样做!

为了获得一些不错的句法效果而进行欺骗充满了危险,并且可能会抹杀未来的发展。

首先,在C++中,任何时候只有一个联合成员是活跃的。因此不能保证切换数组和结构的使用,即使在许多编译器上这可能会产生预期的结果。

然后,不能保证结构成员是连续的,因此如果混合使用数组和结构可以工作,它可能仍然不会导致正确的结果,即使在许多编译器上这将按预期工作.

或者用更安全的方法来做...

如果您仍然喜欢混合使用数组的特定颜色分量 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、a 成为特定数组项的引用。然后你确定你可以混合访问方式,你绝对确定两者之间的映射是正确的。

但更喜欢干净的封装

你最初的方法和我的解决方法的问题是它们破坏了封装:你必须知道你的颜色的内部结构才能使用它。

采用这种方法,您将永远无法进化。例如切换到 CMYK 配色方案,或采用位域编码都会受到影响。

正确的做法应该是有一套getters和setters来对外界完全隐藏内部结构。当然,从语法上看,它看起来不太好,但是你真的可以编写真正通用的颜色代码,其中编码方案可以是 compile-time 策略。

最后,我决定使用继承(正如 Ben Voigt 所说)。 我解决了另一个问题,联合使代码不安全,使用这个答案提出的绝妙方法: