我有一组函子用于计算对象范围内的特定内容。基本上,每个仿函数都实现operator()
:
template <typename Iterator1,
typename Iterator2> double operator()( Iterator1 it1,
Iterator2 it2 ) const
{
return( 0.0 );
}
我现在有一组可以创建的对象与不同的仿函数。我通过模板创建者函数来解决这个问题:
template <class Functor> Foo createFoo( ... // some parameters for foo objects
Functor f = Functor() )
{
// calculate stuff for "foo" using functor "f"
}
我现在想要委托仿函数选择给我的程序用户,所以我决定创建一个仿函数工厂。给定一个仿函数的描述性名称,我想创建适当的仿函数,以便它可以用于创建所有Foo
个对象,如上所述。
这是我陷入困境的地方:我无法创建一个返回模板仿函数的工厂,因为如果不编码我想要创建的仿函数的确切类型,我就无法调用此函数。
我考虑过使operator()
成为某个基类的虚函数,即FunctorBase
,但我不希望与虚函数调用相关的性能开销。避免上述开销是我首先选择使用模板的原因。
我在这里陷入僵局,并且肯定会感谢一些评论。
修改:
我打算做什么(代码无效):
DistanceFunctor f = createFunctor( "Bar" ); // Create a functor from a client-supplied string
Foo createFoo( ..., // parameters for foo
f );
在评论中,也建议使用虚拟功能。但是,如上所述的当前仿函数设计不适用于虚函数,因为编译器无法使函数模板成为虚拟函数。调整仿函数类以将两个Iterator类型作为模板参数是可能的,但非常笨重。
修改:
仿函数的工作方式类似于FLANN中使用的仿函数。 See the git repository for an example。我没有看到如何以不同的方式指定这些仿函数。
答案 0 :(得分:1)
在考虑了一下你的要求之后,这是我想出的第一件事:
您的不同仿函数显然无法按照现在定义的方式从公共基类派生,因为您无法生成模板operator()
虚拟。但是,如果您将模板参数从操作员推送到仿函数本身,可以使该操作符成为虚拟:
template <class Iterator>
struct Functor {
virtual double operator()(Iterator it1, Iterator it2) const = 0;
};
这有什么帮助?初看Functor级别的模板看起来不太好,因为您现在必须知道createFunctor
调用之外的参数,实际上,如果调用它,则必须显式指定迭代器类型:
//some concrete functors
template <class It>
struct FuncImpl_Bar : Functor<It> { /* ... implement op()(It, It) ... */ }:
template <class It>
struct FuncImpl_Meow : Functor<It> { /* ... implement op()(It, It) ... */ }:
template <class Iterator>
std::shared_ptr<Functor<Iterator>> createFunctor(std::string const& str)
{
if (str == "Bar") return std::make_shared<FuncImpl_Bar<Iterator>>(/* args *);
else return return std::make_shared<FuncImpl_Meow<Iterator>>(/* args *);
}
//...
auto MyFunctor = createFunctor<???>("Bar"); //what iterator type???
但是AFAICS你不需要知道createFoo
之外的仿函数的确切类型 - 如果createFoo
知道该类型就足够了:
Foo createFoo( ... // some parameters for foo objects
std::string const& str ) //look mum, no templates!
{
typedef whatever_the_container_i_use::iterator Iter;
Functor<Iter> MyFunctor = createFunctor<Iter>(str);
// calculate stuff for "foo" using functor "f"
}
//...
auto myFoo = createFoo(args, "Bar");
auto myOtherFoo = createFoo(args, "Moo");
简而言之:将工厂参数传递到您知道迭代器类型的位置,即您必须使用仿函数工厂参数化的类型。在工厂中调用所需的每个输入,即类型和非类型参数。