重用可变参数类型

Mih*_*los 2 c++ variadic-templates c++14

在下面的C++ 14代码中,我想使用可变参数模板创建一个PossibleTypes容器.接下来,我想创建另一个容器,其中包含先前指定类型的成员元组.

怎么会这样做呢?我想让Foo包含一个<int,double>元组,就像模板化的主题类型一样.

提前谢谢了.

#include <iostream>
#include <tuple>
#include <type_traits>

template <typename... T>
struct PossibleTypes {};

PossibleTypes<int,double> topics;

template <typename... T>
struct Foo{
    std::tuple<T...> member;
};

int main(){
    Foo<??(topics)??> x;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Yak*_*ont 10

有不止一种方法可以做到这一点.您无需了解所有内容,只需找到具有所需功能的内容即可.

以下是三种截然不同的方法.

从实例转录到模板

template<class Src, template<class...>class Dest>
struct transcribe;
template<class Src, template<class...>class Dest>
using transcribe_t=typename transcribe<Src,Dest>::type;

template<template<class...>class Src, class...Ts, template<class...>class Dest>
struct transcribe<Src<Ts...>, Dest>{
  using type=Dest<Ts...>;
};
Run Code Online (Sandbox Code Playgroud)

然后:

transcribe_t<decltype(topics), Foo> x;
Run Code Online (Sandbox Code Playgroud)

通过修改Foo而侵入

这也可以通过修改Foo为捆绑而不是包来侵入.

template <class Bundle>
struct Foo;

template <typename... T>
struct Foo<PossibleTypes<T...>>{
  std::tuple<T...> member;
};
Run Code Online (Sandbox Code Playgroud)

要么

template <template<class...>class Z, typename... T>
struct Foo<Z<T...>>{
  std::tuple<T...> member;
};
Run Code Online (Sandbox Code Playgroud)

然后:

Foo<decltype(topics)> x;
Run Code Online (Sandbox Code Playgroud)

如果你不只是传递一组...参数,这可能会更实用.

基于价值的元编程

我们也可以使用基于价值的元编程来解决这个问题:

template<class T>
struct tag_t {constexpr tag_t(){} using type=T;};
template<class T>
constexpr tag_t<T> tag{};
template<template<class...>class Z>
struct ztemplate_t {
  constexpr ztemplate_t() {}
  template<class...Ts> using apply=Z<Ts...>;
  template<class...Ts>
  constexpr tag_t<Z<Ts...>> operator()(tag_t<Ts>...)const{ return {}; }
};
template<template<class...>class Z>
constexpr ztemplate_t<Z> ztemplate{};

template<class Tag>
using type=typename Tag::type;

template <class... T>
struct PossibleTypes {
  template<template<class...>class Z>
  constexpr auto operator()(ztemplate_t<Z> z) const {
    return z(tag<T>...);
  }
};
Run Code Online (Sandbox Code Playgroud)

给我们:

int main(){
  type<decltype( topics(ztemplate<Foo>) ) > x;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

这很漂亮. 实例.

tag将类型提升为值. ztemplate将模板提升为值.

ztemplate<some_template>( tag<T0>, tag<T1> )返回tag适用some_templateT0, T1喜欢的结果tag_t<some_template<T0, T1>>.

要从标记返回到某个类型,我们会执行此操作type<decltype(some_tag_expression)>.

我修改了你PossibleTypes也有一个operator()(ztemplate)将模板应用于存储的类型PossibleTypes.

随着您进行越来越多的基于类型的操作,这种疯狂效果会更好,因为C++中基于值的编程比模板语法更具表现力且更易于使用.