
on Thu Nov 06 2008, "Joachim Faulhaber" <afojgo-AT-googlemail.com> wrote:
Hi,
I am pondering about functor passing. Functors occur in my library (ITL) e.g. for the aggregation of associated values on insertion in interval_maps (aggregation on overlap):
template<class Domain, class Codomain, ...> class interval_map{ ... //(1) My current implementation is this: // Combinator is the aggregating functor template, // instantiated at compiletime template<template<class>class Combinator> interval_map& add(const value_type& value_pair) { /*Combinator template passed or instantiated somewhere*/ } ... }
//I like this definition, because it's abstract: // The functor has to be a matching template e.g. inplace_max interval_map<int,int> m; m.add<inplace_max>(some); //(1)
template<class Domain, class Codomain, ...> class interval_map{ //(2) The more traditional definition template<class Combinator> interval_map& add(const value_type& value_pair) { /*Combinator type passed or called somewhere*/ } ...
m.add<inplace_max<int> >(some); //(2)
I prefer (1) but both definitions (1) and (2) are purely static denotations. To have adaptable functors or functors that can have states, like in ...
Try a unary MPL lambda expression here instead: m.add<inplace_max<_> >(some);
m.add(some, max_under(42));
... I am afraid I have to say sayonara to definition (1) and use this instead:
template<class Domain, class Codomain, ...> class interval_map{ //(3) Adaptable functor template<template<class>class Combinator> interval_map& add(const value_type& value_pair, const Combinator<Codomain>& combine) { /*combine functor passed or called somewhere*/ }
Presumably because you want to support stateful combine functions?
Now, there seems to be a convention from the STL that functors shall be passed BY VALUE.
Ja.
template<template<class>class Combinator> interval_map& add(const value_type& value_pair, Combinator<Codomain> combine);
This is stated in [Sutter & Alexandrecu 2005, C++ Coding Standards] item 89: "Function objects are modeled on function pointers. Like function pointers, the convention is to pass them by value. All of the standard algorithms pass objects by value, and your algorithms should too."
I do not really understand this convention and feel some resistance to follow it. In addition the call by value implementation can (and will) lead to heavy inefficiency by unaware usage of fat functors.
Sounds like a job for move semantics.
So I browsed through some boost libraries and found that functors are passed by reference there (e.g. accumulators, fusion).
Look for "move.hpp" headers in various library subdirectories :-) -- Dave Abrahams BoostPro Computing http://www.boostpro.com