[英]Is there any way to strip a tuple of pairs to variadic template types or instantiat something with variadic types?
[英]How do I strip a tuple<> back into a variadic template list of types?
有没有办法来剥夺一个std::tuple<T...>
为了拿回来T...
?
例子
假设vct<T...>
是一个预先存在的可变参数类模板,
using U = std::tuple<int,char,std::string>;
using X = vct<int,char,std::string>;
using Y = vct< strip<U> >; // should be same as X
笔记
我知道std::tuple_element ,但我需要所有元素,其形式可用作T...
作为参考,我发现这个问题,这是类似的,但我的需求是较为简单(所以我希望有一个简单的解决方案):所有我需要的是那些在类型列表中tuple
-我不在乎tuple
实例的实际值。
template<typename>
struct strip;
template<typename ...T>
struct strip<std::tuple<T...>>
{
using type = vct<T...>;
};
然后将其用作:
using Y = strip<U>::type;
现在Y
与X
相同。
不,这是不可能的。 参数包是类型推导的结果,不能在其他上下文中产生。
你可以用这种方式做类似于你要求的事情:
template<template<typename...> class T, typename>
struct instantiate_with_arg_pack { };
template<template<typename...> class T, typename... Ts>
struct instantiate_with_arg_pack<T, std::tuple<Ts...>>
{
using type = T<Ts...>;
};
template<typename... Ts>
struct vct { };
int main()
{
using U = std::tuple<int,char,std::string>;
using X = vct<int,char,std::string>;
using Y = instantiate_with_arg_pack<vct, U>::type;
}
实际上,您不需要将参数包保存在元组中:任何可变参数类模板都可以:
template<template<typename...> class T, typename>
struct instantiate_with_arg_pack { };
template<
template<typename...> class T,
template<typename...> class U, // <===
typename... Ts
>
struct instantiate_with_arg_pack<T, U<Ts...>>
// ^^^^^^^^
{
using type = T<Ts...>;
};
template<typename... Ts>
struct vct { };
int main()
{
using U = std::tuple<int,char,std::string>;
using X = vct<int,char,std::string>;
using Y = instantiate_with_arg_pack<vct, X>::type;
// ^
// Won't fire
static_assert(
std::is_same<Y, vct<int,char,std::string>>::value,
"Error!");
}
这是一个活生生的例子。
你不能直接“返回”一个参数包,所以你需要的是这样的:
template< typename... Ts >
struct vct
{ ... };
template< typename T >
struct make_vct;
template< typename... Ts >
struct make_vct< std::tuple< Ts... > >
{
typedef vct< Ts... > type;
};
并使用
using Y = make_vct< U >::type;
这里的目标是能够将参数包从模板实例复制到另一个模板。 我没有将其限制为tuple
,因为...为什么将其限制为tuple
?
template<template<typename...>class Target, typename Src>
struct copy_pack_types;
template<template<typename...>class Target, template<typename...>class Src, typename... Ts>
struct copy_pack_types< Target, Src<Ts...> > {
typedef Target<Ts...> type;
};
template<template<typename... Ts>class Target, typename Src>
using CopyPackTypes = typename copy_pack_types<Target, Src>::type;
#include <string>
#include <tuple>
template<typename... Ts> struct vct;
template<typename... Ts> struct vct2;
using U = std::tuple<int,char,std::string>;
using X = vct<int,char,std::string>;
using Y = CopyPackTypes< vct, U >; // should be same as X
using Z = CopyPackTypes< vct2, U >; // should be different from X
#include <iostream>
#include <type_traits>
int main() {
std::cout << std::is_same< X, Y >::value << "\n";
std::cout << std::is_same< Z, Y >::value << "\n";
std::cout << std::is_same< Z, vct2<int,char,std::string> >::value << "\n";
}
正如预期的那样,输出为“1 0 1”。
CopyPackTypes
采用目标模板和从参数包构造的源类型作为其唯一参数。 然后它将参数包复制到目标模板。
一种标准技术是携带参数包,即创建一个否则不使用的类型,如:
template<typename...>
struct types {};
它仅作为类型列表的占位符存在。 然后您可以将其中的一些传递给另一个模板,并且每个包不会相互“踩踏”。 当您需要将它应用到目标模板时,您可以使用类似上面的“ CopyPackTypes
”来应用它。
类似的技术用于索引包:
template<size_t...>
struct seq {};
否则无用的类型是“黑色石板”,可以携带大量参数。
使用 c++17 std::apply
。
using U = std::tuple<int, char, std::string>;
using X = vct<int, char, std::string>;
using Y = vct<strip<U>>; // should be same as X
auto my_y = std::apply(
[](auto... ts) {
using Y = vct<decltype(ts)...>;
return Y{};
},
U{});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.