c++ - 编译时高效地从 boost::hana 元组中删除重复项
问题描述
我使用该boost::hana
to_map
函数从类型元组中删除重复项boost::hana
。在编译器资源管理器中查看。该代码运行良好,但编译时间很长(~10s)。我想知道是否存在与boost::hana
元组兼容的更快的解决方案。
#include <boost/hana/map.hpp>
#include <boost/hana/pair.hpp>
#include <boost/hana/type.hpp>
#include <boost/hana/basic_tuple.hpp>
#include <boost/hana/size.hpp>
using namespace boost::hana;
constexpr auto to_type_pair = [](auto x) { return make_pair(typeid_(x), x); };
template <class Tuple>
constexpr auto remove_duplicate_types(Tuple tuple)
{
return values(to_map(transform(tuple, to_type_pair)));
}
int main(){
auto tuple = make_basic_tuple(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40
, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50
, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60
, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70
);
auto noDuplicatesTuple = remove_duplicate_types(tuple);
// Should return 1 since there is only one distinct type in the tuple
return size(noDuplicatesTuple);
}
解决方案
我没有运行任何基准测试,但您的示例在 Compiler Explorer 上似乎不需要 10 秒。但是,我可以解释为什么它是一个相对较慢的解决方案,并提出一个替代方案,假设您只对获取唯一的类型列表感兴趣,而不在结果中保留任何运行时信息。
创建大型元组和/或实例化在其原型中具有大型元组的函数模板是昂贵的编译时操作。
只需调用transform
为每个元素实例化一个 lambda,然后实例化对。这个调用的输入/输出都是大元组。
每次创建一个新元素时,对每个元素的调用to_map
都会为空map
并递归调用,但在这种简单的情况下,中间结果将始终是. 我敢打赌,如果您的实际用例不是微不足道的,那么这会增加您的编译时间。(这在我们实施时肯定是一个问题,因此我们避免了这种情况,因为它预先拥有所有输入)。insert
map
hana::map<int>
hana::map
hana::make_map
所有这一切,对于在运行时代码中使用的这些大型函数类型来说,会有很大的损失。如果您将操作包装在其中decltype
并仅使用结果类型,您可能会注意到不同之处。
或者,使用原始模板元编程有时可以产生优于基于函数模板的元编程的性能结果。这是您的用例的示例:
#include <boost/hana/basic_tuple.hpp>
#include <boost/mp11/algorithm.hpp>
namespace hana = boost::hana;
using namespace boost::mp11;
int main() {
auto tuple = hana::make_basic_tuple(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40
, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50
, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60
, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70
);
hana::basic_tuple<int> no_dups = mp_unique<std::decay_t<decltype(tuple)>>{};
}
推荐阅读
- python - 当min(list)采用科学计数法时如何修复list.index(min(list))
- php - 如何修复 Yii2 高级模板中的“前端\模型\模型”必须有主键错误
- ssh - 在气流 SSHOperator 中使用映射驱动器
- c# - 有没有办法根据两个数组集的索引禁用一对匹配的按钮?
- eclipse - 如何引用属性引用而不是“命名”引用?
- javascript - 如何使用 expres-validator 获取验证错误?
- python-3.x - Google Vision,ImageAnnotatorClient 错误:代码:3,消息:“错误的图像数据。”
- mysql - 在 MySQL 中加载了 ST_GeomFromGeoJSON 的multiplygon 内的搜索点
- python - 如何在单独的位置连接 2 个熊猫列?
- c++ - 不完整的类模板问题 - C++