C++ 虚拟模板函数的替代方案

C++ 虚拟模板函数的替代方案,c++,templates,inheritance,polymorphism,virtual,C++,Templates,Inheritance,Polymorphism,Virtual,我有一个抽象的UI类,它需要能够向用户请求一些输入。 此函数是模板化的,因为可以要求不同的内容 但是,这个函数也必须是虚拟的,因为我希望UI的派生类能够 提供自己的实现(aCommandLineUI需要与 WebBasedUI) 类用户界面{ // ... 公众: //询问一些意见 模板 虚拟T askFor(const std::string&mesg)const=0; //询问但提供默认回退 模板 虚拟T askFor(常数std::string&mesg,常数T&def)常数=0; } 类

我有一个抽象的
UI
类,它需要能够向用户请求一些输入。 此函数是模板化的,因为可以要求不同的内容

但是,这个函数也必须是虚拟的,因为我希望
UI
的派生类能够 提供自己的实现(a
CommandLineUI
需要与
WebBasedUI

类用户界面{
// ...
公众:
//询问一些意见
模板
虚拟T askFor(const std::string&mesg)const=0;
//询问但提供默认回退
模板
虚拟T askFor(常数std::string&mesg,常数T&def)常数=0;
}
类CommandLineUI:UI{
// ...
公众:
模板
虚拟T askFor(const std::string&mesg)const{
//实施细节
}
模板
虚拟T askFor(常数std::string&mesg,常数T&def)常数{
//实施细节
}
}
<>上述代码将无法工作,因为模板化方法不能在C++中是虚拟的, 因为我无法理解的原因

我读过一些关于访问者模式或类型擦除能够解决此问题的文章,但我不知道如何解决。(我试着翻译答案中的例子
类似的堆栈溢出问题,但没有成功。)

在这种情况下,标准非常简单

§14.5.2.3)成员功能模板不得是虚拟的。[示例:

模板结构AA{
模板虚空g(C);//错误
虚拟void f();//确定
};
-[结束示例]

基本上,您将如何实现它们?vtable看起来像什么

如果您只需要一个“可流化”的类型,我建议您查看库。它可能不能完全解决你的问题,但它相当整洁。您将需要以下内容:

using Inputable = any<
    mpl::vector<
        copy_constructible<>,
        typeid_<>,
        istreamable<>
    >
>;

virtual Inputable askFor(const std::string& mesg) const = 0;
使用Inputable=any<
向量<
可构造的副本,
typeid_2;,
可扩展
>
>;
虚拟可输入askFor(const std::string&mesg)const=0;

可能比这更复杂,我只使用了这个库,但它可以让你有一个虚拟的“模板”成员函数,只要你清楚地定义你需要模板类型做什么。(请注意,还有一个
any_cast
,因此调用者知道他想要得到什么类型,他总是可以将结果投射到它。)

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

模板函数不能是
虚拟的
。虚拟函数不能是模板,因为在编译时必须知道重载的数量。但是,如果在代码中的某个地方执行
ui.askFor()
,则在不同编译单元中创建的对象的vtable将丢失该条目。这里的问题是,您试图混合使用运行时和编译时多态。为什么不定义一组受支持的类型?通常情况下,你可以很好地使用int、float、string、datetime、它们的列表、它们的字典等集合。看起来你并没有认真考虑这个设计。您将如何为实现
命令行ui::ask?当我调用
ui->askFor(“输入frobnitator:”)
时会发生什么?
askFor
适用于流中可以读取的所有内容。为
int
double
string
等编写自定义函数的问题在于,实现代码会非常重复,而且
askFor
函数非常复杂。。。
template <class T> struct AA {
    template <class C> virtual void g(C); // error
    virtual void f(); // OK
};
using Inputable = any<
    mpl::vector<
        copy_constructible<>,
        typeid_<>,
        istreamable<>
    >
>;

virtual Inputable askFor(const std::string& mesg) const = 0;