根据liveworkspace.org,对于g ++(4.7.2),clang(3.2)和icc(13.0.1)的最新版本,这个问题的答案是有效的,但根据Stephen Lin的评论,它取决于empty base optimization以及std::tuple
的实施。
如果我有一个如下所示的模板结构:
template<
class T1, unsigned short N1,
class T2, unsigned short N2
>
struct ComboThree {
T1 data_1[N1];
T2 data_2[N2];
};
我可以通过专门化来避免零长度数组和额外的对齐填充:
template<class T1, class T2>
struct ComboThree<T1, 0, T2, 0> {
};
template<class T1, class T2, unsigned short N2>
struct ComboThree<T1, 0, T2, N2>
{
T2 data_2[N2];
};
template<class T1, unsigned short N1, class T2>
struct ComboThree<T1, N1, T2, 0>
{
T1 data_1[N1];
};
但是当TX / NX对的X变得更大时,像这样的专业化变得麻烦。在我的项目中,不同组合的实际数量可能会少于五个,所以我最终可能根本不使用模板,但我很好奇:
有没有办法使用TEMPLATE MAGIC来避免零长度数组,同时避免占用任何额外空间?
例如,这个:
template<class T, unsigned short N>
struct Array {
T data[N];
};
template<class T>
struct Array<T, 0> {};
template<
class T1, unsigned short N1,
class T2, unsigned short N2
>
struct ComboTwo {
Array<T1, N1> data_1;
Array<T2, N2> data_2;
};
避免了零长度数组,但空结构占用了额外的空间。另一方面,这个:
template<class T, unsigned short N>
struct Array {
T data[N];
};
template<class T>
struct Array<T, 0> {};
template<
class T1, unsigned short N1,
class T2, unsigned short N2
>
struct ComboFour : Array<T1, N1>, Array<T2, N2> {};
似乎做了我想做的事(是吗?),但我不知道如何访问数组中的数据&lt;&gt;基础结构在我的程序中。 It also has other limitations noted by Stephen Lin below.
答案 0 :(得分:2)
这不是一个完整的答案,但很难适应评论。要访问ComboFour
的子对象,如果您真的想要做最后一个选项,则需要以下丑陋的语法:
ComboFour<int, 2, float, 1> cf;
cf.Array<int, 2>::data[0] = 0;
cf.Array<int, 2>::data[1] = 1;
cf.Array<float, 1>::data[0] = 2.0f;
您可以使用一些访问器功能来清理它,但它仍然不会很好。
但更大的问题是,以下是一个错误:
ComboFour<int, 1, int, 1> cf2 // fails to compile
因为同一个班级不能两次用作父母。
(另请注意,Array<T, 0>
的{{1}}个子对象可能会占用零空间,也可能不会占用零空间,这称为“空基本优化”,并且标准允许但不是必需的。)< / p>
可能有一些方法可以解决第二个问题......我认为继承ComboFour
{可能会或可能不会使用标准库实现的内部空基础优化来实现} {{1}如果你真的不得不这样做,可能是最简单的方法,但它会使语法变得更加丑陋。
编辑:这适用于GCC 4.7.2
std::tuple<...>
以后......
Array<T, N>
(老实说,标准库或多或少需要空基优化才能使用,所以即使不需要它我也会感到惊讶,如果最近的编译器不支持它;是否template<
class T1, unsigned short N1,
class T2, unsigned short N2,
class T3, unsigned short N3
>
struct Combo : std::tuple<Array<T1, N1>, Array<T2, N2>, Array<T3, N3>>
{
};
在书面上正确地利用这种优化是另一回事。)