我想知道是否有一种实用的方法可以使用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<;T></对于每个T,code>是不同的类型。但是,我们可以通过给出每个Foo<;T>一个公共基类,具有指向它的指针映射,并使用虚拟函数将call()分派到相应的子类
不过,对于这种情况,参数的类型也必须始终相同。正如@MSalters所提到的,std::any可以对此有所帮助
最后,我们可以使用pimpl模式包装所有这些内容,这样看起来只有一个整洁的Foo类型:
#包括<;卡塞特>;
#包括<;字符串>;
#包括<;功能性>;
#包括<;任何>;
#包括<;无序地图>;
#包括<;记忆>;
结构Foo{
公众:
模板<;typename T,typename FunT>;
空集(FunT fun){
pimpl=std::使独特<;FooImpl<;T,FunT>;;(std::移动(乐趣));
}
//使用操作符()而不是call()使其成为函子,这
//它更灵活一点。
void运算符()(const std::any&;arg){
断言(pimpl);
pimpl->;呼叫(arg);
}
私人:
结构IFooImpl{
virtual~IFooImpl()=默认值;
虚拟无效调用(const std::any&;arg)const=0;
};
模板<;类参数,类型名称FunT>;
结构FooImpl:IFooImpl
{
FooImpl(FunT-fun):fun(std::move(fun)){}
无效调用(const std::any&;arg)const覆盖{
乐趣(标准:任何演员<;Arg>;(Arg));
}
私人:
FunT-fun;
};
标准::唯一性;
};
//使用示例
#包括<;iostream>;
空心条(int v){
标准::cout<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;<;;
}
int main(){
std::无序映射<;std::字符串,Foo>;表格;
表[“aaa”]。设置为“int”>bar;
//甚至可以使用模板/通用lambdas!
表[“bbb”]。设置“浮动”([](自动x){
std::可以用“x”调用“bbb”\n;;
});
表[“aaa”](14);
表[“bbb”](12.0f);
}
参见导栓上的说明