如何解决使用boost mp11有效地打开运行时值完成处理功能时中断
我有以下code,其中我在运行时值上实现分派,以某种方式解释数据(在此玩具示例中,数据可以是uint8_t或short)。
代码似乎可以工作,但是我想知道是否可以以某种方式对代码进行微优化,以便在命中(处理函数匹配)时停止处理(当前,即使元组的第一个元素是“处理程序”,整个元组也是如此)。在运行时进行迭代)。
#include <boost/mp11/tuple.hpp>
#include <iostream>
uint8_t data[4] = {0,1,100,2};
template<int runtimeId,typename T>
struct kindToType{
static constexpr int id = runtimeId;
using type = T;
};
const auto print =[]<typename T> (const T* data){
if constexpr(std::is_same_v<short,std::remove_cvref_t<T>>){
const short* values = (const short*)data;
std::cout << values[0] << " " << values[1] << std::endl;
} else if constexpr(std::is_same_v<uint8_t,std::remove_cvref_t<T>>){
const uint8_t* values = (const uint8_t*)data;
std::cout << (int)values[0] << " " << (int)values[1]<< " " << (int)values[2] << " " << (int)values[3] << std::endl;;
}
};
static constexpr std::tuple<kindToType<10,uint8_t>,kindToType<11,short>> mappings{};
void dispatch(int kind){
boost::mp11::tuple_for_each(mappings,[kind]<typename Mapping>(const Mapping&) {
if (Mapping::id == kind)
{
print((typename Mapping::type*)data);
}
});
}
int main()
{
// no guarantee that kind is index like(e.g. for two values
// it can have values 47 and 1701)
dispatch(10);
dispatch(11);
}
注意:
- 我不能/不想使用std :: variant。
- 我不想使用std :: map或std :: unordered map(其中值为
std::function
) - 我知道这是过早的优化(假设处理程序完成大量工作,即使进行10次整数比较也很便宜)。
- 我的处理程序是唯一的,即它是std :: map之类的东西,而不是std :: multimap之类的东西,所以
break;
很好。 - 用于运行时值的id类型不能保证其值在[0,n-1]中。
- 只要在至少1个编译器中实现,我对C ++ 20解决方案就可以了。
解决方法
这的运行时性能在很大程度上取决于元组的大小。您可以创建自己的for_each_tuple
实现,以便在执行函数时尽早实现:
template<typename FuncTuple,typename Selector>
void tuple_for_each(FuncTuple const& funcTuple,Selector selector)
{
std::apply([selector](auto const& ...funcs)
{
(void)(selector(funcs) || ...);
},funcTuple);
}
您的调度将如下所示:
void dispatch(int kind)
{
tuple_for_each(mappings,[kind]<typename Mapping>(const Mapping&)
{
std::cout << "loop,";
if (Mapping::id == kind)
{
print((typename Mapping::type*)data);
return true;
}
return false;
});
}
如果您摆脱了lambda中的模板,而使用auto
,则此代码将在C ++ 17中编译。我们利用操作员短路来发挥我们的优势,因此编译器将为我们提供早期解决方案。 Here是完整代码。
另外,请注意,强制转换(const short*)data
是UB。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。