2013-04-08 55 views
0

我有对象上的计算范围上的具体的东西了一套仿函数。实际上,每个函数对象实现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); 

在评论中,利用虚函数建议为好。但是,上述的当前仿函数设计不适用于虚函数,因为编译器无法使函数模板变为虚拟。调整仿函数类以将两个迭代器类型作为模板参数是可能的,但非常笨重。

编辑

的仿函数的工作方式与FLANN中使用的那些。 See the git repository for an example。我不明白如何以不同的方式指定这些函子。

+0

你能展示你打算如何一起使用所有这些功能吗? – 2013-04-08 13:21:19

+2

“性能开销”是否可衡量?虚函数调用是否会受到很大的伤害,即分析器是否告诉你它们是一个至关重要的性能瓶颈?或者,你是否让你的生活稍微难一点,做过早的优化? – 2013-04-08 13:29:51

+0

@ArneMertz:我还没有实现其他变种。我认为,如果每个函数都被应用于数百万个对象,虚拟函数可能会减慢我的速度。因此:您可能是对的: -/ 我将执行其他变体并返回一些结果。 – Gnosophilon 2013-04-08 14:14:14

回答

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"); 

简而言之:向下合格出厂参数的地步,你知道Iterator类型,即您必须对函数f进行参数化的类型与...一起工作。打电话给你知道的工厂,每需要输入,即类型和非类型参数。

+0

谢谢,这是一个很好的解决方案。我现在正在考虑重写这个设计,因为你的解决方案清楚地表明了我最初设计中的一些缺点。感谢您的输入 :) – Gnosophilon 2013-04-15 06:36:04