Boost logo

Boost :

From: Eric Niebler (eric_at_[hidden])
Date: 2008-03-22 23:18:27


Steven Watanabe wrote:
> AMDG
>
> Markus Werle wrote:
>> Now we introduce another function call - not an operator
>> this time, but in C++ these are equivalent.
>>
>> struct fun_t {};
>> terminal<fun_t>::type const fun = {{}};
>>
>> fun(a, b);
>>
>> This is represented by something similar to
>>
>> expr<
>> tag::function
>> ,args3<
>> ref_<expr<tag::terminal, args0<fun_tag> > const>
>> ,expr<tag::terminal, args0<> >
>> ,expr<tag::terminal, args0<> >
>> >
>> >
>>
>> This is suprising. In contrast to operator+, the function fun
>> is treated as if it was an *operand*, not an *operator*.
>> The expression is not tagged by _the_ function call, but by a
>> global this-is-a-function-tag and the function is stored in the
>> argument typelist.
>>
>
> I don't find it surprising. This behavior is exactly what I would expect.
>
> fun(a, b) is equivalent to fun.operator()(a, b). In a concept fun(int, int)
> will be represented as
>
> concept Callable<class T> {
> void operator()(T, int, int);
> };
>
> if I recall correctly.

Precisely. Another way to see this is to consider that the following
might be a valid expression within a domain:

   (a+b)(a-b);

That's equivalent to (a+b).operator()(a-b). Clearly, this needs to be
encoded as a binary tree with (a+b) as the left child and (a-b) as the
right, with tag::function.

To see a real-world example that uses operator() this way, see:
http://boost-sandbox.sourceforge.net/libs/proto/doc/html/boost_proto/users_guide/examples/map_assign.html

It's an implementation of the map_list_of() function from the
Boost.Assign library. It lets you initialize a map as follows:

     // Initialize a map:
     std::map<std::string, int> op =
         map_list_of
             ("<",1)
             ("<=",2)
             (">",3)
             (">=",4)
             ("=",5)
             ("<>",6)
         ;

>> What fun means is context dependent, I would expect the context
>> to take care about what fun_t might mean, so if we want
>> symmetry first I'd expect a type representation similar to
>>
>> expr<
>> tag::function<fun_t>
>> ,args2<
>> ,expr<tag::terminal, args0<...ommitted...> >
>> ,expr<tag::terminal, args0<...ommitted...> >
>> >
>> >
>>
>>
>> So I wonder whether this asymmetry was introduced due to the
>> fact that function objects could have a state which makes them
>> an in-between between operator and operand ...
>>
>
> IMO, a function object is not an operator at all. The operator
> involved is the function call operator which takes a reference to
> the function object (*this) as the first parameter. I don't see this
> as being any more asymmetric than any other member function call.

Right, it's perfectly symmetric with all the other operators.

-- 
Eric Niebler
Boost Consulting
www.boost-consulting.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk