Boost logo

Boost :

Subject: Re: [boost] compile time parser generator
From: John Bytheway (jbytheway+boost_at_[hidden])
Date: 2012-01-08 10:58:00


On 08/01/12 09:42, Ábel Sinkovics wrote:
> Hi Martin,
>
>> I'm not sure it's possible to get a string literal in a
>> template< char ...>
>> class string;
>> 'Literals transformation is redefined into two distinct phases: raw
>> and cooked. A raw literal is a sequence of characters of some specific
>> type, while the cooked literal is of a separate type. The C++ literal
>> 1234, as a raw literal, is this sequence of characters '1', '2', '3',
>> '4'. As a cooked literal, it is the integer 1234. The C++ literal 0xA
>> in raw form is '0', 'x', 'A', while in cooked form it is the integer 10.
>>
>> Literals can be extended in both raw and cooked forms, with the
>> exception of string literals, which can only be processed in cooked
>> form. This exception is due to the fact that strings have prefixes
>> that affect the specific meaning and type of the characters in
>> question.' - source: wikipedia -
>> http://en.wikipedia.org/wiki/C%2B%2B11#User-defined_literals .
> Right below that Wikipedia describes a variadic template-based
> mechanism, where the compiler instantiates a template operator and
> passes the characters as template arguments to it. The return type of
> that operator could be an MPL list of boxed characters and we could
> access it using decltype - at least this is the idea.

That interface is only available for integer and floating-point
literals, not string literals (which that page also says). The only way
to get at characters of a string literal at compile time is through
constexpr functions.

> Your approach is different than ours, since it is based on constexpr
> while ours is based on template metaprogramming. I think it would be
> interesting to compare the two. Could you implement something like the
> type-safe printf using this approach? (Parsing the format string at
> compile-time, generate a list of expected types and type check the rest
> of the printf arguments.)

(disclaimer: I've not written any serious code; I'm just pondering and
playing around)

I *thought* it was possible to make something like this work:

printf<const_string("%d %d\n")>(11, 13);

but it doesn't work in gcc 4.6, and, on closer reading of N3290, it's
not supposed to work. Values of integral and enumeration types are
still the only values we can pass as template arguments.

It seems that the only way to take the output of a constexpr function
(which is necessarily a value) and turn it into something type-ish (as
needed to type-check a printf call) is to go via an integer. So, my
next idea was:

printf<format("%d %d\n")>(11, 13);

where format returns some packed integer representation of (int, int). I
guess you need ~4 bits to encode each argument type, so with 64-bit ints
it could support up to 16 arguments. This would allow type-checking,
but unfortunately the actual format string has been thrown away and
isn't available for use by printf, so the best I can see is this:

printf<format("%d %d\n")>("%d %d\n", 11, 13);

wrapped up in a macro so you don't have to pass the format string twice.
 And that sucks.

Can anyone see a better solution?

John Bytheway


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