gpt4 book ai didi

c++ - 删除虚拟调用

转载 作者:行者123 更新时间:2023-11-30 02:41:06 25 4
gpt4 key购买 nike

数据以下列形式从给定 channel 到达:

void DispatchIncomingChannelData(uint8_t const typeId, 
void * payload,
uint32_t const payloadSize);

有效载荷可能有几种类型:

struct PayloadA { /* Various Data */ };
struct PayloadB { /* Various Data */ };
struct PayloadC { /* Various Data */ };
// Other PODs...

然后分派(dispatch)给相应的处理程序:

void ProcessPayload_A(PayloadA * payload) { /* PayloadA code */ }
void ProcessPayload_B(PayloadB * payload) { /* PayloadB code */ }
void ProcessPayload_C(PayloadC * payload) { /* PayloadC code */ }

没有模板,人们可以简单地提供一个开关,然后扔掉!使用模板,我开始如下:

struct BasePayloadProcessor abstract
{
public:
virtual void ProcessPayload(void * const payload, uint32_t const payloadSize) = 0;
};

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

template<typename T>
struct TypedPayloadProcessor : BasePayloadProcessor
{
public:
using PayloadHandler = void (*)(T * message);

TypedPayloadProcessor(uint8_t const typeId, PayloadHandler payloadHandler) :
_payloadHandler { payloadHandler },
_type { typeid(T) },
_typeId { typeId }
{ }

virtual void ProcessPayload(void * const payload, uint32_t const payloadSize) override
{
ASSERT(_payloadHandler);
ASSERT(payloadSize == sizeof(T));
T * t = reinterpret_cast<T *>(payload);
_payloadHandler(t);
}

private:
PayloadHandler _payloadHandler;
type_info const & _type; // <-- These two members are
uint8_t const _typeId; // <-- not really necessary
};

为了测试,定义了一个枚举,一个处理器数组,并对它们进行了硬编码。

enum class PayloadTypes : uint8_t
{
Invalid = 0x00,
A = 0x01,
B = 0x02,
C = 0x03,
// etc...
TotalTypes = static_cast<uint8_t>(PayloadTypes::C) + 0x01
};

// array of base class pointers
std::array<BasePayloadProcessor *, static_cast<uint8_t>(PayloadTypes::TotalTypes)> payloadProcessors { };

// populate the array
payloadProcessors[static_cast<uint8_t>(PayloadTypes::Invalid)] = nullptr;
payloadProcessors[static_cast<uint8_t>(PayloadTypes::A)] = new TypedPayloadProcessor<PayloadA>(static_cast<uint8_t>(PayloadTypes::A), ProcessPayload_A);
payloadProcessors[static_cast<uint8_t>(PayloadTypes::B)] = new TypedPayloadProcessor<PayloadB>(static_cast<uint8_t>(PayloadTypes::B), ProcessPayload_B);
payloadProcessors[static_cast<uint8_t>(PayloadTypes::C)] = new TypedPayloadProcessor<PayloadC>(static_cast<uint8_t>(PayloadTypes::B), ProcessPayload_C);
// etc....

并实现了如下派发功能:

void DispatchIncomingChannelData(uint8_t const typeId, 
void * payload,
uint32_t const payloadSize)
{
ASSERT(typeId > static_cast<uint8_t>(PayloadTypes::Invalid));
ASSERT(typeId < static_cast<uint8_t>(PayloadTypes::TotalTypes));
payloadProcessors[typeId]->ProcessPayload(payload, payloadSize);
}

一切正常。但是我对这个解决方案不满意。我更愿意摆脱基类,而不是保留指针数组(由于缓存行)。我确信有更好的方法。最终,我打算允许开发人员“注册”他们的类型处理程序。谢谢。

最佳答案

我认为使用包装器构建的 function 数组会更容易:

using CallbackFn = std::function<void(void*, const uint32_t)>;

template <typename T>
CallbackFn make_processor(void (*func)(T*))
{
return [=](void* payload, const uint32_t size){);
ASSERT(payloadSize == sizeof(T));
func(static_cast<T*>(payload));
};
}

这样,您就可以直接传递已有的处理函数,让一切正常运行:

std::array<CallbackFn, 
static_cast<uint8_t>(PayloadTypes::TotalTypes)> payloadProcessors;

payloadProcessors[static_cast<uint8_t>(PayloadTypes::A)] =
make_processor(ProcessPayload_A);
payloadProcessors[static_cast<uint8_t>(PayloadTypes::B)] =
make_processor(ProcessPayload_B);
payloadProcessors[static_cast<uint8_t>(PayloadTypes::C)] =
make_processor(ProcessPayload_C);

关于c++ - 删除虚拟调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28482921/

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