Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2003-02-02 14:00:44


Terje Slettebø <tslettebo_at_[hidden]> writes:

>>From: "David Abrahams" <dave_at_[hidden]>
>> 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 ***?
>
> I'm not sure what you mean, here. The error above comes from argument type
> mismatch, as the type of "x" is unsigned int, while static_log2<> expects an
> unsigned long, so there needs to be a conversion. Therefore, the partial
> specialisation doesn't work.

Exactly. My point is that as far as the template mechanism is
concerned, int, long, and class are all completely disjoint kinds of
metadata -- with one exception: int and long constants are allowed to
inter-convert when you pass one where the other is expected.

> As you note, if you change it to match, with unsigned long, it
> works. I think EDG is right on this one, that there has to be an
> exact match, except top-level cv-qualification.

cv-qualification?? Whoa, the compiler seems to accept them, but
they're also ignored. This compiles:

    template <const volatile int x> struct foo;
    template <template <int x> class> class bar {};
    bar<foo> x;

>> > 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.
>
> You can use the syntax Genny used: "argument_type < static_log2<16> > ::
> type". However, unless you use an arbitrary default argument for
> static_log2, just for this purpose, you need to specify an arbitrary
> constant, instead, as shown here, just to get the type.

You can do that, but IIUC it won't get you where Genny's trying to go:
namely that if static_log2 happens to get adjusted so its parameter is
an unsigned long long constant, you can detect that without causing an
error.

-- 
                       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