Boost logo

Boost :

From: Joel de Guzman (joel_at_[hidden])
Date: 2003-10-09 10:04:16


David B. Held <dheld_at_[hidden]> wrote:
> "David Abrahams" <dave_at_[hidden]> wrote in message
> news:uvfqze84g.fsf_at_boost-consulting.com...
>> "Joel de Guzman" <joel_at_[hidden]> writes:
>>> [...]
>>> struct square
>>> {
>>> template <class X>
>>> struct sig { typedef X type; }
>>> X operator()(X x) { return x * x; }
>>> };
>
> I don't understand this example. Is operator() also supposed to
> be templated?

Yes, sorry... It sould read:

    struct square
    {
        template <class X>
        struct sig { typedef X type; }
        template <class X>
        X operator()(X x) { return x * x; }
    };

> If so, what connects sig<> with operator()?

It answers the question "given an argument X, what will be
square's return type?" Consider the plus:

    struct plus
    {
        template <class X, class Y>
        struct sig { typedef typeof(X() + Y()) type; }

        template <class X, class Y>
        typeof(X() + Y()) operator()(X x, Y y) { return x + y; }
    };

>> [...]
>> b. It should be called apply, because that just makes it
>> cheaper and easier to use: instead of
>> [...]
>
> But my understanding is that apply<> is the compile-time way
> to spell "operator()" for function objects. If sig<> is really
> the definition of R for "R operator()", without being the result
> of operator(), should it really be spelled "apply<>"? It seems
> to me that there is a confusion between runtime and compile
> time here. The fact that apply<> works syntactically adds to
> the confusion.
>
> In Joel's example above, square could be a metafunction
> object as well as a function object. But what kind of
> metafunction is it? It's the identity metafunction. Clearly,
> this is different from it's name and run-time purpose. That's
> because sig<> does not reflect it's intent, only its return
> value to support lazy evaluation.
>
> So in this case, I think calling the return type metafunction
> "apply<>" is confusing, even though it makes it convenient
> to use with MPL::lambda. I think I agree with Joel that it
> should be called result<>. Even though it *could* be used
> with lambda, how would you do so? The result of apply<>
> is not square, as one would hope, but X. What are you
> going to do with the return type by itself?
>
> There definitely needs to be a convention. And maybe
> ReturnTypeMetafunction needs to be a formal concept
> that encapsulates that convention and specifies a name.
> But I don't think the name should be "apply<>".

Exactly. Gosh, I wish I was as eloquent as you guys are! :-)
Anyway, in Doug's paper: A uniform method for computing
function return types", It is spelled "result" and not "apply"

see http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1454.html

In this context:

If the implementation cannot determine the type of the expression f(t1, t2, ..., tN), or if the
expression is ill-formed, the implementation shall use the following process to determine the
member type type:
  1.. If F is a function type, type is the return type of the function type F.

  2.. If F is a member function type, type is the return type of the member function type F.

  3.. If F is a function object defined by the standard library, the method of determining type
is unspecified.

  4.. If F is a class type with a member type result_type, type is F::result_type.

  5.. If F is a class type with no member named result_type or if F::result_type is not a type:

    1.. If N=0 (no arguments), type is void.
    2.. If N>0, type is F::result<F(T1, T2, ..., TN)>::type.
  6.. Otherwise, the program is ill-formed.

<< The syntax is slightly different, however. Anyway, right now, I am
doing a rewrite of Phoenix to follow Doug's proposed conventions. >>

Regards,

--
Joel de Guzman
http://www.boost-consulting.com
http://spirit.sf.net

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