我正在阅读Andrei Alexandrescu的
Modern C++ Design Generic Programming and Design Patterns Applied和关于多方法的第11章正好解决了我想要解决的问题.本书的所有源代码都发布在名为
Loki的库中.
问题在于该书相当陈旧(2001)并处理了在C 11中不再适用的限制(例如,模板参数的数量不能变化).我试着查看Loki是否已经使用C 11进行了重写,但是最后一次修改是在2009年,并且在Andrei Alexandrescu’s home page没有更新.但是,在做了一些研究之后我觉得Loki就像它在某种意义上就像Boost一样被纳入标准库.
解决方法
它不在标准中,但使用由一对typeid索引的函数对象的映射构建起来相当容易.
为了完整起见,这是我的第一次尝试:
#include <iostream> #include <typeinfo> #include <typeindex> #include <map> #include <functional> #include <memory> struct Animal { virtual std::type_index type() const = 0; }; template <class T> struct AnimalImpl : public Animal { std::type_index type() const override { return typeid(T); } }; struct Dog : AnimalImpl<Dog> { }; struct Cat : AnimalImpl<Cat> { }; struct Mouse : AnimalImpl<Mouse> { }; using Types = std::tuple<std::type_index,std::type_index>; using Outcome = std::function<void (Animal&,Animal&)>; using DispatchMap = std::map<Types,Outcome>; using namespace std; void catVDog(Animal& cat,Animal& dog) { cout << "dog wins\n"; } void catVMouse(Animal& cat,Animal& mouse) { cout << "cat wins\n"; } DispatchMap makeOutcomes() { DispatchMap result; result.emplace( make_pair( Types {typeid(Cat),typeid(Dog)},catVDog) ); result.emplace( make_pair( Types {typeid(Dog),typeid(Cat)},[](Animal&a1,Animal&a2) { return catVDog(a2,a1); }) ); result.emplace( make_pair( Types {typeid(Cat),typeid(Mouse)},catVMouse) ); result.emplace( make_pair( Types {typeid(Mouse),Animal&a2) { return catVMouse(a2,a1); }) ); return result; } const DispatchMap outcomes = makeOutcomes(); void fight(Animal& a1,Animal& a2) { auto it = outcomes.find(Types{ a1.type(),a2.type() }); if (it == outcomes.end()) { cout << typeid(a1).name() << " " << typeid(a2).name() << " "; std::cout << "no fight\n"; } else { it->second(a1,a2); } } int main() { unique_ptr<Animal> cat { new Cat {} }; unique_ptr<Animal> dog { new Dog {} }; unique_ptr<Animal> mouse { new Mouse {} }; fight(*cat,*dog); fight(*cat,*mouse); fight(*dog,*cat); fight(*dog,*mouse); return 0; }