如何在现代C ++中基于另一组可变参数模板参数表示可变参数模板类型? [英] How to represent a variadic templated type based on another group of variadic template arguments in modern C++?

查看:76
本文介绍了如何在现代C ++中基于另一组可变参数模板参数表示可变参数模板类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我具有以下可变参数模板结构:

Suppose I have a following variadic template structure:

template <class... T> 
struct Example {};

现在我想定义一个模板函数:

Now I want to define a template function:

template<class... S>
??? f() {
    return Example<???>
}

其中 Example<>的专业化取决于 f 的模板参数 S

where the specialization of Example<> is depend on the template parameter S of f.

更具体(和简单),现在我只想返回 Example< int,...,int> ,其中 int 是参数包 S 的大小。

To be more concrete (and simple), now I just want to return Example<int, ...,int>, where the number of int is the size of the parameter pack S.

如何在现代C ++中完成,例如C ++ 11/14/17?

How can it be done in modern C++, i.e. C++11/14/17?

更多通常,是否可以在编译时定义模板参数的函数?

More generally, is there a way to at compile time define a function on template parameters?

推荐答案

在进行模板元编程时,IMO始终有助于尽可能长时间地保持元部分和非元部分的分离。这样,您可以首先考虑元部分,就好像它是普通程序一样,对类型而不是值进行操作。因此,模板变成一个函数,以某种类型(或用于高阶编程:其他模板)作为输入并返回某种类型(或用于高阶编程:其他模板)。

When doing template meta programming, IMO it always helps to keep the "meta part" and the "non meta part" separate for as long as possible. That way you can first think about the "meta part" as if it were a normal program, operating on types instead of values. So a template becomes a function, taking some type(s) (or for "higher order programming": other templates) as input and returns some type (or for "higher order programming": other templates).

因此,首先,退后一步,不要考虑模板,元编程等。您有一个列表 S 。对于 S 的每个项目,您都想调用一些函数,并组合一个返回项目的列表。因此,您需要一个函数,该函数在给定列表的一个项目的情况下,返回它映射到的项目。我们将此函数称为 mapping 。您还需要一个具有上述功能并将其应用到列表的函数,即在每个项目上调用 mapping 并组合结果列表。我们称之为 map

So, first, step back for a second and don't think about templates, metaprogramming, and such. You have a list S. For each item of S, you want to call some function, and assemble a list of the returned items. So you need a function that, given one item of the list, returns the item it's mapped to. Let's call this function mapping. You also need a function which takes said function and applies it to your list, i.e. calls the mapping on each item and assembles the result list. Let's call that map.

现在将其转换为元程序:

Now turn this into a meta program:

// mapping :: TYPE -> TYPE
// ---------------------------------------------------------
// ?? --> int (default "value")
template<typename X> struct mapping {
  using type = int;
};
// if instead you want it to be undefined for unknown types:
//template<typename X> struct mapping;
// bool --> double
template<> struct mapping<bool> {
  using type = double;
};

现在 map ,因此可以使用类似 mapping

Now map, generalized such that it can use anything like mapping:

// map :: ([T] -> T) -> (T -> T) -> ([T] -> T)
//         "List"       "Mapping"   result "type" (also a "List")
// --------------------------------------------------------
template<template<typename...> class List,
         template<typename> class Mapping>
struct map {
  template<typename... Elements>
  using type = List<typename Mapping<Elements>::type...>;
};

最后,应用到您的 Example (其中是一种列表,因为它持有多种类型)和具体的映射

Finally, apply to your Example (which is kind of a list, because it "holds" multiple types) and the concrete mapping:

template<typename... S>
using MappedExample = map<Example, mapping>::type<S...>;

现在您已经有了生成的模板,可以在非元程序中使用它:

Now you've got the resulting template, use it in your non-meta program:

template<typename... S>
MappedExample<S...> f() {
  return MappedExample<S...>{};
}

实时示例

int main() {
  std::cout
    << typeid(Example<bool,int,char,double>).name()
    << std::endl
    << typeid(decltype(f<bool, int, char, double>())).name()
    << std::endl;
}

输出:


7ExampleIJbicdEE 在第一行中,表示具有模板参数 b的 Example ool, i nt, c har, d ouble。

7ExampleIJdiiiEE 作为第二行,表示一个示例,其模板参数为 d ouble(从布尔值映射),其中3个为 i nt(默认映射)。

7ExampleIJbicdEE in the first line, means an Example with template parameters bool, int, char, double.
7ExampleIJdiiiEE as second line, means an Example with template parameters double (mapped from the bool) and 3 int (the default mapping).

这篇关于如何在现代C ++中基于另一组可变参数模板参数表示可变参数模板类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆