c++ - 使用boost mp11有效地打开运行时值(处理函数完成时中断)

标签 c++ c++20 boost-mp11

我有以下code我在运行时值上实现调度,以某种方式解释数据(在这个玩具示例中,数据可以是 uint8_t 或短整型)。

代码似乎可以工作,但我想知道是否可以以某种方式对代码进行微优化,以便当我命中(处理函数匹配)时,处理会停止(目前即使元组的第一个元素是“处理程序”,整个元组也是在运行时迭代)。

#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] 范围内。
  • 只要 C++20 解决方案在至少 1 个编译器中实现,我就可以接受。

最佳答案

其运行时性能在很大程度上取决于元组的大小。您可以创建自己的 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。

关于c++ - 使用boost mp11有效地打开运行时值(处理函数完成时中断),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63344585/

相关文章:

c++ - 与 Boost.Mp11 : "expected a class template, got ' T'"斗争

c++ - 空默认构造函数与隐式定义的不同机器代码

c++ - 我可以让 lambda 推断出变体返回类型吗?

c++ - boost mp11 中 "quoted metafunction"的目的是什么?

c++ - 未能尝试定义 Boost::mp11::find_if 谓词

c++ - 模块最终允许标准库实现中的可读名称吗?

c++ - 如何使用 nlohmann json 在 C++ 中将相同的关键 json 数据合并为一个

c++ - 动态大小的 boost::asio::buffer

c++ - 没有第二个操作数的三元运算符

c++ - gcc '-m32' 选项在不运行 valgrind 时更改浮点舍入