gpt4 book ai didi

c++ - 根据运行时数据选择函数重载?

转载 作者:搜寻专家 更新时间:2023-10-31 00:39:04 26 4
gpt4 key购买 nike

我使用 boost msm 库创建了一个有限状态机。事件及其转换在编译时以声明方式定义。然而,在运行时,需要一些代码根据输入数据选择正确的事件。目前代码如下所示:

enum : unsigned {
fin = (1 << 0),
syn = (1 << 1),
ack = (1 << 4)
// etc...
};

// events
struct receive_syn {};
struct receive_syn_ack {};
struct receive_fin {};
struct receive_fin_ack {};
struct receive_ack {};
// etc..

void receive(const Segment& segment)
{
switch (segment.getFlags())
{
case syn|ack: state_machine.process_event(receive_syn_ack{}); break;
case syn: state_machine.process_event(receive_syn{}); break;
case fin|ack: state_machine.process_event(receive_fin_ack{}); break;
case fin: state_machine.process_event(receive_fin{}); break;
case ack: state_machine.process_event(receive_ack{}); break;
// etc..
}
}

它有效,而且速度可能很快。但是,我觉得这应该以更具声明性的风格来编写。

如何在不引入额外的运行时开销的情况下以更高级别的编程风格实现这一点?

作为引用,这里有一个 boost::msm example .

最佳答案

警告!未经测试。

您可以使用编译时映射将标志连接到要传递的对象类型:

template < unsigned tflags, typename ttype >
struct kv
{
static const unsigned flags = tflags;
using type = ttype;
};


using flag_type_map = std::tuple
<
kv<syn|ack, receive_syn_ack>,
kv<syn , receive_syn >,
kv<fin|ack, receive_fin_ack>,
kv<fin , receive_fin >,
kv<ack , receive_ack >
>;

为了在运行时处理它,您必须进行某种迭代或递归。如果编译器足够智能(和内联),您可以获得相同的性能。

template < typename >
struct tuple_pop;

template < typename T, typename... TT >
struct tuple_pop < std::tuple < T, TT... > >
{
using type = std::tuple < TT... >;
};

template < typename T >
void call(unsigned flags, std::true_type)
{
throw std::invalid_argument("flag combination not known / invalid");
}

template < typename T >
void call(unsigned flags, std::false_type = {})
{
using tuple_first = typename std::tuple_element<0, T>::type;
using tuple_popped = typename tuple_pop<T>::type;
using is_last = std::integral_constant<bool,
0 == -1+std::tuple_size<T>::value >;

if(flags == tuple_first::flags)
{
// could replace this hard-wired call with a passed function object
// to make it more generic
state_machine.process_event( typename tuple_first::type{} );
}else
{
create_obj<tuple_popped>(flags, is_last{});
}
}

void receive(const Segment& segment)
{
call<flag_type_map>(segment.getFlags());
}

关于c++ - 根据运行时数据选择函数重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16948732/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com