在我的真实代码中,我正在解析一系列作为连续消息的字节。消息头中的整数决定解释字节的适当方式
为了简化 SO 假设如下:
1
意味着使用struct MsgA
2
意味着使用struct MsgB
3
意味着使用struct MsgC
- 任何其他值均无效
另外对于 SO 假设有一个类,NamePrinter
负责:
- 接收类型(
MsgA
、MsgB
、 或之一MsgC
) - 实例化该类型
- 调用该类型的一些方法(为了示例,仅在下面的代码中调用一个方法)
我知道如何为此编写代码。我还知道如何切换到NamePrinter
另一个也对消息执行操作的类。我不知道该怎么做是选择NamePrinter
在更一般的情况下调用(或另一个类)的哪个成员函数
#include <iostream>
// Some made up "message" structs
struct MsgA final {
static constexpr int getId() { return 1; }
const char* getName() const { return "MsgA"; }
const char* getSomethingElse() const { return "SomethingElseA"; }
};
struct MsgB final {
static constexpr int getId() { return 2; }
const char* getName() const { return "MsgB"; }
const char* getSomethingElse() const { return "SomethingElseB"; }
};
struct MsgC final {
static constexpr int getId() { return 3; }
const char* getName() const { return "MsgC"; }
const char* getSomethingElse() const { return "SomethingElseC"; }
};
// A class that creates a "message" and performs and action on it
class NamePrinter final {
public:
template <class T>
void onMsgPrintName() const {
T t;
std::cout << t.getName() << std::endl;
}
template <class T>
void onMsgPrintSomethingElse() const {
T t;
std::cout << t.getSomethingElse() << std::endl;
}
};
// A function that can convert an integer into a "message" at compile time but
// is hardcoded to call onMsgPrintName
template <class T>
void intToPrintName(const T& a_caller, const int a_id) {
switch (a_id) {
case MsgA::getId(): a_caller.template onMsgPrintName<MsgA>(); break;
case MsgB::getId(): a_caller.template onMsgPrintName<MsgB>(); break;
case MsgC::getId(): a_caller.template onMsgPrintName<MsgC>(); break;
default:
std::cout << "Runtime error" << std::endl;
}
}
// This is invalid but tries to convey that onMsgPrintName has been replaced
// with a template
//template <class F, class T>
//void intToFunc(const T& a_caller, const int a_id) {
// switch (a_id) {
// case MsgA::getId(): a_caller.template F<MsgA>(); break;
// case MsgB::getId(): a_caller.template F<MsgB>(); break;
// case MsgC::getId(): a_caller.template F<MsgC>(); break;
// default:
// std::cout << "Runtime error" << std::endl;
// }
//}
int main(int argc, char** argv) {
const NamePrinter np;
// This will end up calling NamePrinter::onMsgPrintName
intToPrintName(np, argc);
// I want something like this that allows me to pick what is called
//intToFunc<NamePrinter::onMsgPrintName >(np, argc);
//intToFunc<NamePrinter::onMsgPrintSomethingElse>(np, argc);
return 0;
}
我想知道的是我是否可以用我选择的任意成员函数替换onMsgPrintName
内部。intToPrintName
注释掉的代码显示了执行此操作的尝试,但无法编译
添加另一个间接级别 - 一个知道如何调用任何对象上的特定方法的包装器。沿着
和类似的类
onMsgPrintSomethingElse
。现在将其作为额外参数传递给intToPrintName
:用法: