【问题标题】:Finding first non-empty subtype in template arguments在模板参数中查找第一个非空子类型
【发布时间】:2019-03-26 16:39:19
【问题描述】:

我正在尝试编写一个 C++ 元函数,它返回给我提供的模板参数的第一个非空子类型。

例如:

struct I { using subtype = int; };
struct D { using subtype = double; };
struct E { using subtype = empty ; };

我正在努力实现:

static_assert(std::is_same<int, first_non_empty_subtype<E,E,I>>::value, "the first non-empty subtype should be 'int'");
static_assert(std::is_same<double, first_non_empty_subtype<E,D,I>>::value, "the first non-empty subtype should be 'double'");
static_assert(std::is_same<empty, first_non_empty_subtype<E,E,E>>::value, "since all subtypes are empty, the result is empty");

我最初的想法是使用std::conditional_t 和模板递归:

template <typename T, typename ...Ts>
using first_non_empty_subtype = std::conditional_t<
    !std::is_empty<typename T::subtype>::value, 
    typename T::subtype, 
    first_non_empty_subtype<Ts...>>::type

但是,我并不熟悉为类型别名实现模板递归。

有人可以帮我指出解决这个问题的正确方向吗?

谢谢!

【问题讨论】:

  • 为了使递归起作用,你需要一些东西来破坏递归。在您的示例中,没有这样的事情,而且 AFAIK 不能使用模板别名来完成,您不能以任何方式专门化它们。您可以创建一个仅包含 using subtype = ... 的递归结构并使用它。如果你愿意,你可以制作指向递归结构的模板别名,以便于使用。
  • 感谢您指出这一点!我故意忽略了它,因为我不确定它会如何实现。感谢您解释模板别名如何不能被专门化——@max66 展示了一个使用递归结构的解决方案。

标签: c++ templates recursion variadic-templates template-meta-programming


【解决方案1】:

我建议如下

// ground case: no more types, so empty
template <typename ...>
struct fnes_helper
 { using type = empty; };

// the first type is T and isn't empy; so T
template <typename T, typename ... Ts>
struct fnes_helper<T, Ts...>
 { using type = T; };

// the first type is empty; so recursion
template <typename ... Ts>
struct fnes_helper<empty, Ts...> : public fnes_helper<Ts...>
 { };

template <typename ... Ts>
using first_non_empty_subtype 
   = typename fnes_helper<typename Ts::subtype...>::type;

注意fnes_helper 更专业的版本是empty 类型在第一位的版本,在这种情况下使用的版本也是如此。 遵循另一个特化,即具有通用 T 类型在第一个位置的特化,最后我们有在其他情况下选择的主版本,因此类型列表为空。

还记得在static_assert() 测试中在std::is_same 之后添加{} 或::value

static_assert(std::is_same<int, first_non_empty_subtype<E,E,I>>{},
              "the first non-empty subtype should be 'int'");
static_assert(std::is_same<double, first_non_empty_subtype<E,D,I>>{},
              "the first non-empty subtype should be 'double'");
static_assert(std::is_same<empty, first_non_empty_subtype<E,E,E>>{},
              "since all subtypes are empty, the result is empty");

【讨论】:

  • 酷,谢谢!这就是我要找的。感谢您的快速响应并花时间解释解决方案的工作原理。
猜你喜欢
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 2021-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-06
相关资源
最近更新 更多