$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] Design conventions; passing functors
From: Joachim Faulhaber (afojgo_at_[hidden])
Date: 2009-03-04 16:31:26
2008/12/21 David Abrahams <dave_at_[hidden]>:
>
> on Mon Dec 01 2008, "Joachim Faulhaber" <afojgo-AT-googlemail.com> wrote:
>
>> 2008/11/29 David Abrahams <dave_at_[hidden]>:
>>>
>>>>
>>> A good choice that is both forward-looking and compatible with legacy
>>> code is to implement and document move semantics support (or a
>>> swappability requirement), and pass by value unless there's no need for
>>> an eventual copy.
>>
>> looking at library code the 'eventually being copiedness' of
>> functors seems to be a pragmatical criterion for many library
>> authors on how to pass them (boost:: and even std::).
>> If functors are eventually passed to a std algorithm
>> inside the library code (or other copy intensive code), they are
>> exposed as call by value in the libraries interface. If not they
>> are often exposed as call by const reference parameters in the
>> libraries interface.
>
> Interesting. I'm not sure I see the point, but interesting.
>
>>>
>>>> As written earlier in this thread, I would prefer to pass functors
>>>> const reference, and without additional wrappers (which is done by
>>>> other boost libraries too). I do not call std::algorithms internally.
>>>>
>>>> Please tell me, if there are strong arguments against that.
>>>
>>> Extra copies of rvalues can be expensive, and function objects are often
>>> rvalues.
>>>
>>
>> My own functor passing design head aces have disappeared by my
>> decision *not* to expose the Combine (aggregate) functors in the
>> interface of interval_map member functions at all.
>
> I'm sorry, I have no idea what I just read (and re-read) there. Could
> you rephrase?
>
Sorry for the late answer ... I obviously missed your post over Xmas :(
What I wanted to say was this:
Functors occur in my library (ITL) for the aggregation
of associated values on insertion in interval_maps
(aggregation on overlap):
And I thought about different ways to pass the
aggregating functor like:
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*/ }
...
}
or
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*/ }
All these variants have in common that the functor can
be chosen for the call of the function add.
interval_map<int,int> m;
m.add(interval_value_pair, combiner);
During the discussion I realized that the possibility of
passing the functor to every call of the add function is
*not* desirable. It provides too much flexibility that is
not needed and can lead to unnecessary errors.
To mix the aggregating functors for one interval_map m
m.add(interval_value_pair1, inplace_plus<int>());
m.add(interval_value_pair2, inplace_max<int>());
makes no sense.
So the combine functor should be constant for every
instantiation of an interval_map. (Or at least for every
object). Like the sort order is constant and can not
be changed for every call of insert.
typedef interval_map<int, int, partial_absorber, std::less, inplace_max>
maximizer_interval_mapT;
In this case I do not have to pass the combine functor
with calls of the add member function.
maximizer_interval_mapT maximap;
...
maximap.add(make_pair(itv, x));
// on overlap with itv compute maximum with x
see also maximize example:
http://herold-faulhaber.de/boost_itl/doc/libs/itl/doc/html/boost_itl/examples.html#boost_itl.examples.party
>> I am going to instantiate the Combine functor as template
>> parameter for the interval_map class templates only. Similar
>> to the Compare predicate in associative containers,
>> the Combine functor of interval maps is then invariant for any
>> given interval_map instance and can not change for a
>> constructed interval_map object.
>>
>> This way, I think, the interval_map's interface is more easy
>> to use correctly and harder to use incorrectly.
>
> I'm not sure what you're saying. Are you planning to store an instance
> of the function object in the container? That is the normal behavior of
> standard containers.
>
I thought about that but I do not like the idea to put more than the
compare order object into the container.
Sorry for the delay
Joachim