【问题标题】:Template struct that may or may not have a member可能有也可能没有成员的模板结构
【发布时间】:2018-11-13 22:27:36
【问题描述】:

是否有可能有一个可能有或可能没有成员的结构?像这样的:

template <typename T, typename A = some_type_with_size_0>
struct s {
    T t;
    A aux;
};

具体来说,如果我要求s&lt;int, int&gt;,我会得到一个包含两个ints 的结构,但如果我要求s&lt;int&gt;,我会得到一个只有int 的结构。

【问题讨论】:

  • 听起来有点像 XY 问题,请您详细说明您的用例。 some_type_with_size_0 不会阻止实例化 aux 成员,无论应该是什么类型(void 在 IIRC 中都不起作用)。
  • 如果你想要一个或两个ints,你可以使用std::vector&lt;int&gt; ;) 说真的,我认为如果你举一个小例子来说明你需要什么,这会很有帮助

标签: c++ templates struct


【解决方案1】:

在 C++20 中,可以直接做你想做的事情:

template <typename T, typename A = some_type_with_size_0>
struct s {
    T t;
    [[no_unique_address]] A aux;
};

https://en.cppreference.com/w/cpp/language/attributes/no_unique_address

在 C++17 中,没有直接的方法来指定有条件消失的成员。您需要编写一个成熟的部分专业化,如下所示:

template <typename T, typename A = void>
struct s {
    T t;
    A aux;
};
template <typename T>
struct s<T, void> {
    T t;
};

不幸的是,这需要您重复输入所有常见成员(在这种情况下只有t)。为了避免这种情况,我们可以将条件存在的成员粘贴到基类中:

template <typename T, typename A = void>
struct s : optional_aux<A> {
    T t;
};
template <typename A>
struct optional_aux {
    A aux;
};
template <>
struct optional_aux<void> { };

A = void 的情况下,此基类为空,因此编译器可以自行决定将其完全删除,从而使sizeof(s&lt;T, void&gt;) 可能等于sizeof(T)[[no_unique_address]] 属性基本上使空基类优化也可用于成员。

【讨论】:

  • 我可能会注意到,在 C++20 代码中,s&lt;int&gt; 仍然有一个名为 aux 的成员,这可能对名称隐藏/可见性或其他模板的表达式 SFINAE 很重要。只是sizeof(s&lt;int&gt;)允许变小。
  • @aschepler 你是对的。我在字里行间阅读,并假设只要占用空间,成员就可以存在 OP。
【解决方案2】:

您可以使用可变参数模板:

template <typename...> struct Generic;

template <typename T1> struct Generic<T1> {
  T1 field1;
};

template <typename T1, typename T2> struct Generic<T1, T2> {
  T1 field1;
  T2 field2;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 2017-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多