Any way to have a template function in an abstract base class?
我正在尝试创建一个配置管理器类,它可以通过std::string存储任意对象。
我对接口(抽象基类)的最初想法是这样的(当然这是非常不完整的)
1 2 3 4 5 6 7 8 | class ConfigurationManager { public: static boost::shared_ptr<ConfigurationManager> create(); template<typename T> virtual T getOption(const std::string& name) = 0; }; |
但后来我的编译器指出模板不能是虚拟的(然后我意识到无论如何我都不能导出模板)。
在内部,我将使用boost::any(几乎是运行时检查的void*),但我不想在接口中公开boost::any。
最好的方法是什么?
生成一个返回
1 2 3 4 5 6 7 8 9 | class ConfigurationManager { protected: virtual boost::any getOptionProtected(const std::string& name) = 0; public: static boost::shared_ptr<ConfigurationManager> create(); template<typename T> T getOption(const std::string& name) { return boost::any_cast<T>(getOptionProtected(name)); } }; |
另一种方法是将派生类型的名称传递给
1 2 3 4 5 6 7 8 9 10 11 12 13 | template<typename Derived> class ConfigurationManager { public: static boost::shared_ptr<ConfigurationManager> create(); template<typename T> T getOption(const std::string& name) { // call Derived::getOption return static_cast<Derived*>(this)->getOption(name); } }; |
派生类型
1 2 3 4 5 6 7 8 | class Foo : public ConfigurationManager<Foo> { template<typename T> T getOption(const std::string& name) { // do something Foo-specific here } }; |
最终结果类似于抽象的虚拟函数。这个习语被称为奇怪的重复模板模式。
我不知道
1 2 3 4 5 6 7 8 9 | class ConfigurationManager { public: ... template<typename T> getOption(...); private: virtual getOptionSpecial(...) = 0; //Called within getOption }; |
对这个问题的最佳答案是(部分)为什么我认为这几乎是你所能做的。