重用可变参数类型

时间:2017-08-28 18:11:06

标签: c++ c++14 variadic-templates

在下面的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;
}

1 个答案:

答案 0 :(得分: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...>;
};

然后:

transcribe_t<decltype(topics), Foo> x;

通过修改Foo

来侵入

这也可以通过修改Foo来捆绑而不是包来进行。

template <class Bundle>
struct Foo;

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

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

然后:

Foo<decltype(topics)> x;

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

基于价值的元编程

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

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>...);
  }
};

给我们:

int main(){
  type<decltype( topics(ztemplate<Foo>) ) > x;
  return 0;
}

非常漂亮。 Live example

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

ztemplate<some_template>( tag<T0>, tag<T1> )返回tagsome_template应用于T0, T1的结果tag_t<some_template<T0, T1>>,如type<decltype(some_tag_expression)>

要从标记返回到某个类型,我们会执行PossibleTypes

我修改了您的operator()(ztemplate)也有一个PossibleTypes,可以将模板应用于{{1}}中存储的类型。

当你进行越来越多的基于类型的操作时,这种疯狂行为会更好,因为C ++中基于价值的编程比模板语法更具表现力和易用性。