解压缩字体表
Unpacking a typelist
假设我有一个只接受类型模板参数的函数,我无法更改它的定义/实现。
template < typename T >
void do_it();
现在我有一个常用方式定义的排字表,也无法更改它:
template< typename ...Ts >
struct typelist;
我想实现一个函数,它接受一个类型列表,并在每种类型上运行 do_it():
template< typename List >
void do_them();
到目前为止,我找到的唯一解决方案是:
template< typename T >
void do_them_impl()
{
do_it<T>();
}
template< typename T, typename Ts...>
void do_them_impl()
{
do_it<T>();
do_them_impl<Ts...>();
}
template< template < typename...> class List, typename ...Ts >
void do_them_extract( List<Ts...>&& )
{
do_them_impl< Ts >();
}
template< typename List >
void do_them()
{
do_them_impl( List{} );
}
但是对于我想创建一个单个do_them
函数的每个情况,这都需要 4(!) 个函数。我将需要其中的很多,我不想为每个函数编写四个函数。我错过了什么吗?
C++14 欢迎,C++17 解决方案也是,但标记为这样。
在 C++14 中,您可以使用一些糟糕的技巧来引入有效的包扩展上下文:
template< template < typename...> class List, typename ...Ts >
void do_them_impl( List<Ts...>&& )
{
(void)std::initializer_list<int> {
(do_it<Ts>(), 0)...
};
}
template< typename List >
void do_them()
{
do_them_impl( List{} );
}
这使您可以避免递归模板实例化,这通常更昂贵。
现场演示
在 C++17 中,您可以使用折叠表达式:
template< template < typename...> class List, typename ...Ts >
void do_them_impl( List<Ts...>&& )
{
(do_it<Ts>(), ...);
}
template< typename List >
void do_them()
{
do_them_impl( List{} );
}
现场演示
这是一个利用 C++14 的通用 lambda 的解决方案:
template <typename T>
struct type_ { using type = T; };
template <typename Type>
using type = typename Type::type;
template <typename List>
struct map_;
template <template <typename...> typename Container, typename... Ts>
struct map_<Container<Ts...>>
{
template <typename Fun>
void operator()(Fun&& fun)
{
(void)((int[sizeof...(Ts)]){(fun(type_<Ts>{}), 0)...});
}
};
template <typename List>
auto map = map_<List>{};
然后对于每个函数
#include <iostream>
#include <cxxabi.h>
#include <typeinfo>
template <typename T>
const char * type_name()
{
return abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
}
template <typename T>
void do_it()
{
std::cout << type_name<T>() << std::endl;
}
你可以写:
template <typename List>
void do_them()
{
map<List>([](auto v){ do_it<type<decltype(v)>>(); });
}
template <typename... Ts>
struct typelist {};
int main()
{
do_them<typelist<int, char, bool>>();
return 0;
}
用 -O3 编译得到的汇编与我们简单地连续调用 do_it<int>
、do_it<char>
、 do_it<bool>
一样。
相关文章:
- 使用C++进行运行长度解压缩
- C++ 如何将数组值解压缩为函数参数
- struct.error:解压缩 C++ 结构时,解包需要 288 字节的缓冲区
- 在 Qt(C++) 中使用 QProcess 解压缩 - 提取目录问题
- 浏览压缩文件与游览解压缩它们
- 如何在C++向量中解压缩多个值
- 解压缩 C 样式数组以及C++中的参数包
- 如何在 cpp 中解压缩数字,如果它们是使用 struct.pack(fmt, v1, v2, ..) 打包在 pyth
- 如何使用 Poco::ZIP 压缩/解压缩 zip 文件
- 在编译时解压缩数组扩展数据块 (C++11/14)
- 使用 RtMidi 解压缩 Midi 时间码
- 将参数包解压缩到 std::initializer_list?
- 解压缩可变模板参数
- 解压缩附加的压缩字符串
- 使用 AVX2 将 8 位从 32 位值 (__m256i) 解压缩到__m256的最快方法
- C++宏解压缩并加入
- 解压缩串联的 zlib 流而不读取下一个字节
- 解压缩位大小不能被 8 整除的值流
- 为流运算符返回代理类时解压缩参数
- 如何在 Node.js 中解压缩 c# 打包结构