我有一个抽象的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 ++中虚拟化, 因为高于我的原因。
我阅读了一些关于访问者模式或类型擦除能够解决这个问题的事情,但我没有看到如何。 (我试图翻译答案中的例子 类似的堆栈溢出问题,但这不成功)。
答案 0 :(得分:0)
在这种情况下,标准非常简单
§14.5.2.3)成员函数模板不应是虚拟的。 [示例:
template <class T> struct AA {
template <class C> virtual void g(C); // error
virtual void f(); // OK
};
- 结束示例]
基本上,你会如何实现它们? vtable会是什么样子?
如果您只需要一个“可流式”的类型,我建议您查看Boost.TypeErasure库。它可能无法完全解决您的问题,但它非常整洁。你需要这样的东西:
using Inputable = any<
mpl::vector<
copy_constructible<>,
typeid_<>,
istreamable<>
>
>;
virtual Inputable askFor(const std::string& mesg) const = 0;
可能比这更重要的是,我只使用该库,但只要你清楚地定义你需要你的模板类型,你就可以拥有一个虚拟的“模板”成员函数。 (请注意,还有一个any_cast
,因此调用者知道他想要获得什么类型,他总是可以将结果投射到它。)
答案 1 :(得分:0)
根据您的意见,我建议为界面提供一系列虚拟功能,以支持您想要支持的有限类型。在派生类中,您可以将每个重写函数的调用转发到实现所需功能的单个模板函数。