我有一个抽象的 UI
类,需要能够向用户询问一些输入。
这个函数是模板化的,因为可以要求不同的东西。
但是,这个函数也必须是虚拟的,因为我希望 UI
的派生类能够
提供他们自己的实现(CommandLineUI
需要与
WebBasedUI
)。
class UI {
// ...
public:
// ask some input
template<T>
virtual T askFor(const std::string& mesg) const = 0;
// ask but provide default fallback
template<T>
virtual T askFor(const std::string& mesg, const T& def) const = 0;
}
class CommandLineUI : UI {
// ...
public:
template<T>
virtual T askFor(const std::string& mesg) const {
// implementation details
}
template<T>
virtual T askFor(const std::string& mesg, const T& def) const {
// implementation details
}
}
但是上面的代码是行不通的,因为在 C++ 中模板化的方法不能是虚拟的, 出于超出我的原因。
我阅读了一些有关访问者模式或类型删除能够解决此问题的内容,但我看不出如何解决。 (我试图翻译在答案中找到的例子 类似的堆栈溢出问题,但这没有成功)。
最佳答案
在这种情况下,标准非常简单
§14.5.2.3) A member function template shall not be virtual. [ Example:
template <class T> struct AA {
template <class C> virtual void g(C); // error
virtual void f(); // OK
};
— end example ]
基本上,您将如何实现它们? vtable 会是什么样子?
如果您只需要一种“可流式传输”的类型,我建议您查看 Boost.TypeErasure图书馆。它可能无法完全解决您的问题,但它非常简洁。你需要这样的东西:
using Inputable = any<
mpl::vector<
copy_constructible<>,
typeid_<>,
istreamable<>
>
>;
virtual Inputable askFor(const std::string& mesg) const = 0;
可能比这更复杂,我只玩过那个库,但只要您清楚地定义您需要模板类型做什么,它就可以拥有一个虚拟的"template"成员函数。 (请注意,还有一个 any_cast
,因此调用者知道他想要获得什么类型,他总是可以将结果转换为它。)
关于c++ - 虚拟模板函数的替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26799551/