jma*_*jma 4 c++ polymorphism c++14 c++17
我有一张函数表。看起来像这样:
struct AnimalFunction {
void (*Walk)(int a);
void (*Sing)(int a, int b);
void (*Dance)(int a, int b, int c);
};
using AnimalFunctionTable = map<string, AnimalFunction>;
Run Code Online (Sandbox Code Playgroud)
换句话说,我有行AnimalFunction的和从我知道的某种字符串到本质上是类型的映射。为简单起见,也许我包括一些额外的参数,以便它们都具有相同的签名,而忽略它们不需要的内容:WalkDog(int a, int, int) { ... }。
现在,我必须这样定义功能WalkDog(),SingDog(),DanceDog(),然后WalkGiraffe()和SingGiraffe()(但我们的长颈鹿不跳舞,使他们获得了一些默认的功能,也许我有名字至少)。
我的目标是简化维护。我想写一些模板函数,例如
template<typename AnimalT>
void WalkAnimal(int a) { ... }
Run Code Online (Sandbox Code Playgroud)
这样表就可以只是字符串到类型的映射。(有时我可以编写这样一个通用函数,有时我需要编写一个专门的函数,但是至少我要让编译器来维护我的表。)但是我不相信C ++(在我的情况下为14),尽管可能是升级到17的论点)支持这样的事情。
以字符串开头的原因是由于网络上可访问的API。不能期望其他客户端使用与我的系统相同的C ++类型,因此它们告诉我类似的信息{action: "walk", animal: "dog"}。(这是一个protobuf,不是JSON,但这个问题是文本。)
// What I want to say, in my dreams:
actions[action_string][animal_string](arg1, arg2, arg3);
Run Code Online (Sandbox Code Playgroud)
尽管精确的运算符并不重要,但这里仅作说明。
除了明确编写整个表外,还有其他建议吗?
据我了解,您要替换:
struct AnimalFunction {
void (*Walk)(int a);
void (*Sing)(int a, int b);
void (*Dance)(int a, int b, int c);
};
void WalkDog(int a) {/*..*/}
void SingDog(int a, int b) {/*..*/}
void DanceDog(int a, int b, int c) {/*..*/}
void WalkGiraffe(int a) {/*..*/}
void SingGiraffe(int a, int b) {/*..*/}
std::map<std::string, AnimalFunction> animalFunctions = {
{"Dog", {&WalkDog, &SingDog, &DanceDog}},
{"Giraffe", {&WalkGiraffe, &SingGiraffe, nullptr}},
};
Run Code Online (Sandbox Code Playgroud)
通过类似:
struct AnimalFunction {
void (*Walk)(int a);
void (*Sing)(int a, int b);
void (*Dance)(int a, int b, int c);
};
struct Dog {/*..*/};
struct Giraffe {/*..*/};
template <typename T> void WalkT(int a) {/*..*/}
template <typename T> void SingT(int a, int b) {/*..*/}
template <typename T> void DanceT(int a, int b, int c) {/*..*/}
template <> void DanceT<Giraffe>(int a, int b, int c) {/*Empty*/}
// ...
template <typename T>
AnimalFunction MakeAnimalFunction()
{
return {&WalkT<T>, &SingT<T>, &DanceT<T>};
}
std::map<std::string, AnimalFunction> animalFunctions = {
{"Dog", MakeAnimalFunction<Dog>()},
{"Giraffe", MakeAnimalFunction<Giraffe>()},
};
Run Code Online (Sandbox Code Playgroud)