模板类型擦除

我想知道是否有一种实用的方法可以使用C++17标准编写如下代码:

\include<字符串>
#包括<功能性>
#包括<无序地图>
模板<类别Arg>
结构Foo
{
使用arg_type=arg;
使用fun_type=std::function<void(Arg&)>;
趣味型趣味;
无效调用(Arg&Arg){fun(Arg);}
};
结构条
{
使用map\u type=std::unordered\u map<std::string,Foo>//这是不正确的
地图类型地图;
自动运算符[](std::string name){return map[name];}
};

在上面的代码中,classFoo的模板参数对应于某个不返回任何内容的一元函数的输入类型。具有不同模板类型的Foo的不同实例对应于采用不同类型参数的函数。类Bar的目的只是为这些函数指定一个名称,但是很明显,映射的当前声明是不正确的,因为它需要知道Foo的模板类型

还是这样

不幸的是,通过编译时检查来实现这一点是不可行的。但是,您可以通过运行时检查来提供该功能

映射的值类型只能是一种类型,并且Foo&lt;T&gt</对于每个T,code>是不同的类型。但是,我们可以通过给出每个Foo&lt;T&gt一个公共基类,具有指向它的指针映射,并使用虚拟函数将call()分派到相应的子类

不过,对于这种情况,参数的类型也必须始终相同。正如@MSalters所提到的,std::any可以对此有所帮助

最后,我们可以使用pimpl模式包装所有这些内容,这样看起来只有一个整洁的Foo类型:

#包括&lt;卡塞特&gt;
#包括&lt;字符串&gt;
#包括&lt;功能性&gt;
#包括&lt;任何&gt;
#包括&lt;无序地图&gt;
#包括&lt;记忆&gt;
结构Foo{
公众:
模板&lt;typename T,typename FunT&gt;
空集(FunT fun){
pimpl=std::使独特&lt;FooImpl&lt;T,FunT&gt;;(std::移动(乐趣));
}
//使用操作符()而不是call()使其成为函子,这
//它更灵活一点。
void运算符()(const std::any&amp;arg){
断言(pimpl);
pimpl-&gt;呼叫(arg);
}
私人:
结构IFooImpl{
virtual~IFooImpl()=默认值;
虚拟无效调用(const std::any&amp;arg)const=0;
};
模板&lt;类参数,类型名称FunT&gt;
结构FooImpl:IFooImpl
{
FooImpl(FunT-fun):fun(std::move(fun)){}
无效调用(const std::any&amp;arg)const覆盖{
乐趣(标准:任何演员&lt;Arg&gt;(Arg));
}
私人:
FunT-fun;
};
标准::唯一性;
};
//使用示例
#包括&lt;iostream&gt;
空心条(int v){
标准::cout&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;;
}
int main(){
std::无序映射&lt;std::字符串,Foo&gt;表格;
表[“aaa”]。设置为“int”>bar;
//甚至可以使用模板/通用lambdas!
表[“bbb”]。设置“浮动”([](自动x){
std::可以用“x”调用“bbb”\n;;
});
表[“aaa”](14);
表[“bbb”](12.0f);
}

参见导栓上的说明

发表评论