bug-gplusplus
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Passing function objects by reference


From: Mats Kindahl
Subject: Re: Passing function objects by reference
Date: 10 Oct 2000 19:26:48 +0200

Herve Bronnimann <address@hidden> writes:

> Dear all: I have an expensive function object, which holds some internal
> value (a vector, in fact). I don't want to use the copy constructor!
> The problem is that the STL algorithms (in many implementations, and in
> fact this IS required by the standard, for understandable reasons) pass
> this object by value and not by reference.
> 

[snip] 

> MY QUESTION IS: is this a consequence of the standard, an
> implementation feature proper to g++, and do you believe this should be
> the correct implementation?

AFAIK, it's a consequence of the standard. Sorry, cannot quote the
paragraph right now (just too tired), but it's in 14.8.2. 

Template deduction is done without considering the body of the
function and also without considering "enclosing" deductions (this one
has bit me too).

> MY CONCERN IS: why should the presence of internal aux functions change
> the behavior of a function call? And even if that were the normal
> behavior, should we have to know how the library algorithms are
> implemented? I contend that certainly we shouldn't.

I agree with you: a user of a library function/algorithm should not
have to bother about the implementation. In this case, the "fault" is
in the implementor of the "algorithm2" function: he has to explicitly
forward the template argument to the "algorithm" function (see below).

[snip]

> struct binary_pred {
>   int i;
>   binary_pred() : i(100) {}
>   binary_pred( binary_pred const &c) : i(c.i) {
>     clog << "copy constructor [with i=" << i++ << "]\n";
>   }
>   bool operator() (int j, int k) {
>     clog << "bool operator() [with i=" << i++ << "]\n";
>     return j==k;
>   }
> };
>
> template <class Compare>
> void algorithm(Compare comp) { clog << "algorithm\n"; comp(1,2); }
> 
> template <class Compare>
> void algorithm2(Compare comp) { clog << "algorithm2\n"; algorithm(comp);

Change this to 

    template <class Compare>
    void algorithm2(Compare comp) { 
            clog << "algorithm2\n"; 
            algorithm<Compare>(comp);
    }

> --------------------------------------------------------------------
> 
> This outputs:
> 
>     Call with algorithm<const binary_pred>
>     copy constructor [with i=100]
>     algorithm2
>     copy constructor [with i=101]
>     algorithm
>     bool operator() [with i=102]
>     Call with algorithm<const binary_pred&>
>     algorithm2
>     copy constructor [with i=100]
>     algorithm
>     bool operator() [with i=101]
>     Value of comp: 100

Gives me

    Call with algorithm<binary_pred>
    copy constructor [with i=100]
    algorithm2
    copy constructor [with i=101]
    algorithm
    bool operator() [with i=102]
    Call with algorithm<binary_pred&>
    algorithm2
    algorithm
    bool operator() [with i=100]
    Value of comp: 101

i.e., the copy construction in the second case is not called.

> Replacing algorithm2() calls in main by algorithm() calls outputs:
> 
>     Call with algorithm<const binary_pred>
>     copy constructor [with i=100]
>     algorithm
>     bool operator() [with i=101]
>     Call with algorithm<const binary_pred&>
>     algorithm
>     bool operator() [with i=100]
>     Value of comp: 101
> 
> To illustrate that there might be a problem with the compiler, if you
> call algorithm2<const binary_pred &>(comp), it will not generate any
> warnings, even though comp(1,2) is not a const member function. This is
> because instead of algorithm2<const binary_pred &>, it calls
> algorithm2<binary_pred>. You can force the compiler to show it by
> replacing comp(1,2) by comp() and looking at the error message.

Yes, it copies the binary predicate and passes the copy to
"algorithm". Doing the same replacement in the altered code gives me
the following compiler error:

    g++     passing.cc   -o passing
    passing.cc: In function `void algorithm<const binary_pred &>(const 
binary_pred &)':
    passing.cc:29:   instantiated from `algorithm2<const binary_pred &>(const 
binary_pred &)'
    passing.cc:40:   instantiated from here
    passing.cc:23: passing `const binary_pred' as `this' argument of `bool 
binary_pred::operator ()(int, int)' discards qualifiers


Hope this is of some help,

-- 
Mats Kindahl, IAR Systems, Sweden

Any opinions expressed are my own, not my company's.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]