gpt4 book ai didi

c++ - 类模板中的多个可选成员,无需开销

转载 作者:行者123 更新时间:2023-12-04 16:23:50 27 4
gpt4 key购买 nike

如果我想要一个带有可选成员的类,我正在使用模板特化:

template<class T>
struct X {
T t;
void print() { cout << "t is " << t << '\n'; }
};
template<>
struct X<void> {
void print() { cout << "without T\n"; }
};

这很好,因为没有运行时开销和很少的代码重复。但是,如果我有 3 个而不是 1 个可选类成员,我必须编写 2^3=8 个类,即“小重复”很快变得不合理。

一个可能的解决方案可能是像这样使用 std::conditional:

template<class T1, class T2, class T3>
struct X {
conditional_t<is_void_v<T1>, char, T1> t1;
conditional_t<is_void_v<T2>, char, T2> t2;
conditional_t<is_void_v<T3>, char, T3> t3;

void print() {
if constexpr (!is_void_v<T1>) cout << "t1 is " << t1 << '\n';
if constexpr (!is_void_v<T2>) cout << "t2 is " << t2 << '\n';
if constexpr (!is_void_v<T3>) cout << "t3 is " << t3 << '\n';
}
};

但是现在,我类(class)的对象会浪费内存。我正在寻找某种方法来避免大部分代码重复(在可选成员代码开销的数量上最多呈线性),同时避免花费不必要的运行时间和内存。

请注意,对于单个可选类成员(请参阅 Optional class members without runtime overheadMost efficient way to implement template-based optional class members in C++? )存在此问题(有答案),但据我所知,对于多个可选成员尚未回答。

最佳答案

使用 optional_member 类,

template <class T>
struct OptionalMember
{
T t;
static constexpr bool has_member = true;
};

template<> struct X<void>
{
static constexpr bool has_member = false;
};

您可以使用继承(只要它们的类型不同)和 EBO 来避免额外的内存。

template<class T1, class T2, class T3>
struct X : OptionalMember<T1>, OptionalMember<T2>, OptionalMember<T3>
{
void print() {
if constexpr (!OptionalMember<T1>::has_member)
cout << "t1 is " << OptionalMember<T1>::t << '\n';
if constexpr (!OptionalMember<T2>::has_member)
cout << "t2 is " << OptionalMember<T2>::t << '\n';
if constexpr (!OptionalMember<T1>::has_member)
cout << "t3 is " << OptionalMember<T3>::t << '\n';
}
};

或者,从 C++20 开始,属性 [[no_unique_address]] (只要它们的类型不同,就没有额外的内存)。

template<class T1, class T2, class T3>
struct X {
[[no_unique_address]] OptionalMember<T1> t1;
[[no_unique_address]] OptionalMember<T2> t2;
[[no_unique_address]] OptionalMember<T3> t3;

void print() {
if constexpr (!t1.has_member) cout << "t1 is " << t1.t << '\n';
if constexpr (!t2.has_member) cout << "t2 is " << t2.t << '\n';
if constexpr (!t3.has_member) cout << "t3 is " << t3.t << '\n';
}
};

如果类型可能相同,您可以修改 OptionalMember采取额外的标签(或任何类型的标识符作为 std::size_t ):

template <class T, class Tag>
struct OptionalMember
{
T t;
static constexpr bool has_member = true;
};

template<class Tag> struct X<void, Tag>
{
static constexpr bool has_member = false;
};

然后

struct tag1;
struct tag2;
struct tag3;

并使用 OptionalMember<TX, tagX>而不是 OptionalMember<TX>从上面的解决方案。

关于c++ - 类模板中的多个可选成员,无需开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69222391/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com