虚拟模板功能的替代方案

时间:2014-11-07 10:49:50

标签: c++ templates inheritance polymorphism virtual

我有一个抽象的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 ++中虚拟化, 因为高于我的原因。

我阅读了一些关于访问者模式或类型擦除能够解决这个问题的事情,但我没有看到如何。 (我试图翻译答案中的例子 类似的堆栈溢出问题,但这不成功)。

2 个答案:

答案 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)

根据您的意见,我建议为界面提供一系列虚拟功能,以支持您想要支持的有限类型。在派生类中,您可以将每个重写函数的调用转发到实现所需功能的单个模板函数。