在下面的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;
}
答案 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
来捆绑而不是包来进行。
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> )
返回tag
将some_template
应用于T0, T1
的结果tag_t<some_template<T0, T1>>
,如type<decltype(some_tag_expression)>
。
要从标记返回到某个类型,我们会执行PossibleTypes
。
我修改了您的operator()(ztemplate)
也有一个PossibleTypes
,可以将模板应用于{{1}}中存储的类型。
当你进行越来越多的基于类型的操作时,这种疯狂行为会更好,因为C ++中基于价值的编程比模板语法更具表现力和易用性。