我有一个模板化的结构,该结构具有一个带有额外浮点数的变体,如下所示:
template <bool HasFloat>
struct Foo {
std::vector<int> a;
float b; // Not needed if HasFloat is false
};
为了节省内存(是的,这很重要),如果HasFloat
为false,我想省略float。由于struct
中还有很多其他内容,因此最好的方法如下:
using B = typename std::conditional<HasFloat, float, ZeroSizedType>::type;
B b;
据我所知,除了C ++中没有零大小类型的东西。唯一的例外似乎是“ Flexible Array Members”,所以我也许可以这样做:
using B = typename std::conditional<HasFloat, float, float[]>::type;
除了它们仅在C99中受支持,在C ++中不受支持。
对此的标准解决方案似乎是使用继承,因为基类 的大小可以为零,但是我的结构也可以由程序集访问,并且使程序集更简单,如果float b;
位于结构的末尾,而不是开头,反之that isn't guaranteed。
因此,这似乎让模板专业化成为唯一选择,但我的课实际上很长,我想避免重复所有内容。我还缺少其他解决方案吗?
答案 0 :(得分:2)
我的一位同事提出了一个相当不错的解决方案。它确实需要复制和粘贴数据成员,但是至少我不必重复我的方法。
template <bool HasFloat>
struct Foo {
struct State {
std::vector<int> a;
};
struct StateWithFloat {
std::vector<int> a;
float k;
};
using FooState = std::conditional_t<HasFloat, StateWithFloat, State>;
FooState state;
};
您可以这样做:
struct StateWithFloat {
State state;
float k;
};
但是随后您必须添加模板函数以避免state.a
与state.state.a
的问题,此时复制和粘贴似乎更容易。
@aschepler还指出,在C ++ 20中,您将可以使用[[no_unique_address]]
。
答案 1 :(得分:-2)
您可以创建一个专门针对是否具有float的结构,然后在转发template参数的结构中使用它。像这样:
template <bool HasFloat>
struct PerhapsFloat;
template <>
struct PerhapsFloat<true>
{
float b;
};
template <>
struct PerhapsFloat<false>
{
};
template <bool HasFloat>
struct Foo {
std::vector<int> a;
PerhapsFloat<HasFloat> b;
};
在这里,您有一个演示: https://godbolt.org/z/7zPto9
答案 2 :(得分:-3)
尝试将专业化提取到基类/成员类。
template <bool B>
struct Foo {};
template <>
struct Foo<true>
{
float f;
};
template <bool HasFloat>
class Bar
{
Foo<HasFloat> b;
};
class Empty {};
int main()
{
std::cout << sizeof(Bar<true>) << std::endl; // 4
std::cout << sizeof(Bar<false>) << std::endl; // 1
std::cout << sizeof(Empty) << std::endl; // 1
}