【问题标题】:Why can't we use variadic template at the beginning/middle of template specialization (and how to emulate)?为什么我们不能在模板专业化的开始/中间使用可变参数模板(以及如何模拟)?
【发布时间】:2018-06-16 06:47:11
【问题描述】:

我想知道如何模拟以下内容:

template<class> struct foo; 

template<template<class..., int..., class...> class list,
class... clist1, int... ilist1, class... clist2>
struct foo<list<clist1..., ilist1..., clist2...>> {

};

这个特化(假设)接受一个class,它有任意数量的类,然后是整数,然后是类。目前似乎没有办法直接实现这一点。 (如果您可以评论为什么标准不支持这一点,则可以加分)

Eigen 的线性代数库中的一个例子说明了这种情况何时可行,其中大多数类的结构如下:

Vector<class Scalar_type, int rows, class... options>
Mstrix<class Scalar_type, int rows, int cols, class... options>

启用上述功能后,可以使用接受任何这些基类的元模板函数。因为它不受支持,所以您必须为每个类编写专业。

有没有办法模拟一个模板函数,支持接受上述类?

我正在寻找通用解决方案。 (为每个类写特化不是通用的,我也不是直接在寻找Eigen的库的解决方案,这只是一个例子)


说明示例

假设我想获得template class 的第一类。 不知何故,我从其他一些元模板函数中获得了原始类类型。因此我不知道它的模板参数是什么样的。

也许是:

Vector1&lt;class Scalar_type, int rows, class... others&gt; 或者

Vector2&lt;class Scalar_type, class... others&gt;

因为我没有直接使用类型,所以我的元模板函数必须是 template&lt;class&gt; struct foo; 之类的类型,具有各种专业化。

在这种情况下,getFront 是一个很好的例子,因为我需要 2 个专业:

template<class> struct getFront; 

template<template<class...,int...,class...> class param, 
class... l1, int... l2, class... l3, class first> 
struct getFront<param<first, l1..., l2... l3....> { 
using type = first; };

template<template<class...> class param, class first, class... others>
struct getFront<param<first, others...>> {
using type = first;
};

【问题讨论】:

  • 为什么最有可能是“我们在哪里停下来?”当前的规则禁止一些理论上可行的事情,但它们也比使用一大堆特殊情况或它们的一个或多个复杂概括所得到的要简单得多。
  • 嗯,在我看来,启用这些更复杂的专业化似乎可以在 c++ 语言中启用下一级的编程模型。它还会使诸如获取列表中的最后一个类型之类的事情变得微不足道。 (只是一个我知道迭代仍然很简单的例子)IE:template&lt;class..., class last&gt; getLast { using type = last; };
  • 我们似乎正在转向基于 constexpr 的元编程模型,而不是基于模板的元编程模型。还有其他一些建议可以帮助解决这个问题,比如参数包切片。

标签: c++ c++11 variadic-templates template-meta-programming template-specialization


【解决方案1】:

有没有办法模拟一个模板函数,支持接受上述类?

如下使用模板特化怎么样?

template <typename...>
struct foo;

template <typename ... Ts1, int ... Is, typename ... Ts2>
struct foo<std::tuple<Ts1...>,
           std::integer_sequence<int, Is...>,
           std::tuple<Ts2...>>
 {
 };

或者,如果您更喜欢参数化模板容器,例如

template <template <typename...> class Ct1, typename ... Ts1,
          template <int...> class Ci, int ... Is,
          template <typename...> class Ct2, typename ... Ts2>
struct foo<Ct1<Ts1...>, Ci<Is...>, Ct2<Ts2...>>
 { };

【讨论】:

  • 我正在寻找一种接受class&lt;class..., int..., class...&gt; 类的方法,假设元模板函数可能对constexpr 字段或using 声明感兴趣。在这种情况下,它必须接受实际的类。仅使用 template&lt;class&gt; 也会阻止您执行类似... template&lt;class&gt; struct getFront; template&lt;template&lt;class...,int...,class...&gt; class param, class... l1, int... l2, class... l3, class first&gt; struct getFront&lt;param&lt;first, l1..., l2... l3....&gt; { using type = first; };
  • (从上面继续)(假设)这可能是因为我从另一个 using decl 得到了上面的类,我不知道它的类型是 class&lt;class...&gt; 还是类型 class&lt;class..., int... class&gt;因此我没有能力将所有模板参数包装在std::tuples
  • @JosephFranciscus - 抱歉(也许是我的错:我的英语不好)我不明白你的 cmets 是什么意思。拜托,您能否将问题添加到他们(以便其他感兴趣的人可以轻松看到)以及您想要(或不)编写的代码示例?
  • 用示例编辑。
  • @JosephFranciscus - 我明白了......我理解得更好一些,但我怀疑你想要的实际语言规则是不可能的。这不是不合理的;只是 C++11/14/17 不支持。
猜你喜欢
  • 2014-04-19
  • 1970-01-01
  • 2018-07-31
  • 2011-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多