Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2003-02-02 12:18:58


Gennaro Prota <gennaro_prota_at_[hidden]> writes:

> On Sun, 02 Feb 2003 08:35:56 -0500, David Abrahams
> <dave_at_[hidden]> wrote:
>
>>> This of course works, but the typedef name is quite "log specific";
>>> certainly that's worse than having a generic name available at class
>>> scope:
>>>
>>>
>>> template <...>
>>> struct static_log2 {
>>> typedef ... argument_type; // (*)
>>> };
>>>
>>>
>>> As Terje Slettebø noticed in private mail, this is a general problem
>>> for any 'compile-time function'.
>>
>>("metafunction")
>
> Well, the term 'compile-time function' was mine, so if it is an
> error

It's not an error; I was just trying to say that they're equivalent
terms, for clarity.

> it is my fault, not Terje's. Maybe I'm not aligned to the standard
> terminology, but to me the prefix meta- means "that refers to
> something of its same nature", thus for instance a meta-sentence is a
> sentence that talks about sentences, a metarule is a rule about rules
> and a metaprogram is a program that generates a program. Since a class
> template doesn't generate a function

It can, but not the ones we're discussing.

> I don't call it a metafunction, though of course if you intend
> 'function' in a wider meaning then you can do that as well.

No, I intend "meta-" in the wider meaning of "of or related to
metaprogramming." It's a lot easier to discuss metafunctions and
metadata than compile-time functions, and types, integral constants,
templates, constant pointers and references, pointers and references
to functions, and pointers to members (whew! did I forget anything?)

As long as we're in the domain of metaprogramming, I think it makes
sense to adopt a few linguistic shorthands (i.e. domain-specific
jargon).

> Yes, but it's quite overkilling in this case. At a point, you have to
> balance the generality with the complexity cost (not to talk, in this
> case, about compile times).

You're the one who brought up generality ;-). It's easy enough to get
the speed back by using specializations.

> Sorry, I should have been clearer. The idea was to use a non-intrusive
> way to gather the argument type of a generic unary 'metafunction'. The
> template argument_type<>, to be specialized as needed, provided a
> uniform interface for that; for instance:
>
> template <typename T>
> struct argument_type;
>
> template <>
> struct argument_type<MyMetaFunction> {
> typedef ... type;
> };

Ah. Well, there's no way to do what you want in general. That's just
one among many very good reasons that MPL metafunctions use a truly
polymorphic interface, operating just on types. If metafunctions
aren't themselves polymorphic, you can't do this kind of detection.

> For static_log2 you would specialize it as:
>
> template < unsigned long x >
> struct argument_type< static_log2<x> > {
> typedef unsigned long type;
>
> };
>
>
> That, however, still requires you to specify a number (whatever it is)
> when requiring the argument type:
>
> argument_type < static_log2<16> > :: type

I don't even think it works. Throwing this at Comeau online:

    template <unsigned long N>
    struct static_log2 {};

    template <class T>
    struct argument_type;

    template < unsigned int x > // ***
    struct argument_type< static_log2<x> > {
      typedef unsigned long type;
    };

Yeilds:

    "ComeauTest.c", line 6: error: constant "x" is not used in template argument list
              of class template "argument_type<static_log2<x>>"
         template < unsigned int x >
                                 ^

But this works again if I change *** to unsigned long. None of my
other compilers agree, but I am inclined to believe EDG. Why should
it be any different from substituting "class x" at ***?

> whereas I think the intuitive syntax would be:
>
> argument_type < static_log2<> > :: type
>
> To get the intuitive syntax, you can't use a default value in the
> specialization of argument_type, simply because that's illegal. But
> you could, if you really strive for it at all costs, use a default
> (=0) for static_log2 itself. How ugly (and ad-hoc) that would be is
> evident to everyone, so I was just, to say, thinking out loud in the
> hope that it could suggest other ideas.

IMO, unless EDG is wrong you're going to have to use types if you want
to generalize it.

-- 
                       David Abrahams
   dave_at_[hidden] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

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