I was thinking about language feature allowing convert string literal
into variadic character pack (char...).
Here is real life use case, which comes from Yard parser library
(http://yard-parser.sourceforge.net/cgi-bin/index.cgi).
It shall define parser that matches sequence of characters.
Exact implementation doesn't matter.
It has been slightly modified to use variadic templates
template <char Char1_, char Char2_, char...MoreChars_>
class CharSeq
{
static const unsigned int length = sizeof...(MoreChars_) + 2;
inline static char get_nth(unsigned int n);
public:
template <typename ParserState_>
static bool match(ParserState_& state);
};
typedef CharSeq<'c', 'a', 't', 'c', 'h'> CatchKeyword;
// which could be:
//typedef CharSeq<"catch"> CatchKeyword;
There is proposal of 'User-defined literals' (http://www.open-std.org/
jtc1/sc22/wg21/docs/papers/2007/n2378.pdf), but atleast in my
understanding, it fails to provide way of doing that.
Is my assumption is correct?
If yes, what are technical reasons from preventing that?
Cheers, Piotr Rak
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
the current standard does not support Variadic Templates they may be
added in the c++ox revision
i do not think any c++ compilers other than gcc support this
http://www.osl.iu.edu/~dgregor/cpp/variadic-templates.html
so i fyou do wnat portable code or are using som other compiler you
would need to declare
your class templates with the required number of template parameters.
> There is proposal of 'User-defined literals' (http://www.open-std.org/
> jtc1/sc22/wg21/docs/papers/2007/n2378.pdf), but atleast in my
> understanding, it fails to provide way of doing that.
User-defined literals receive a C-string.
That's a fairly inefficient design, of course.
> If yes, what are technical reasons from preventing that?
None really.
It just seems people working on the standard are not that interested
in compile-time computation.
Ideally, strings should be manipulable at compile-time as easily as at
runtime. There are so many uses to this (especially for parser
generators and the like).
The op's question seems to be about the C++0x standard as it exists at
this time, which supports things like variadic templates. He's asking
whether there is some mechanism in the in progress C++0x standard that
would allow him to take apart a string literals character by character
at compile time using a template metaprogram.
IMO the OP is aware that *current* C++ does not have
variadic templates. But realizing that C++0x will
be finished somewhere in 2009 his example is quite
reasonable, because variadic templates do have *very*
high chances to be introduced into C++0x.
I find his extension proposal to allow a string-literal
as an alternative argument of variadic non-type templates
(of character type) quite interesting. This is IMO the
first approach, where I would see any chance of acceptance
on implementors side.
Early proposals - which had no variadic templates available
and usually reasoned about 'char const*' template parameters -
lead to several problematic situations, which I do not
see to exist for this proposal.
Just my personal 2 Euro cent,
Daniel Krügler
"*very* high" is understating it. They are in the draft, and with a
working implementation already, there are chances of about nil +- zero
of getting removed for some reason.
> I find his extension proposal to allow a string-literal
> as an alternative argument of variadic non-type templates
> (of character type) quite interesting. This is IMO the
> first approach, where I would see any chance of acceptance
> on implementors side.
> Early proposals - which had no variadic templates available
> and usually reasoned about 'char const*' template parameters -
> lead to several problematic situations, which I do not
> see to exist for this proposal.
Yeah. This is a good idea. It doesn't take a lot of wording either:
Under [temp.arg.nontype], paragraph 1, add "a string literal" as
another element of the list. Replace paragraph 2 with "A string
literal shall only appear as the last template parameter (including
default parameters)." Add a new paragraph that says "A string literal
non-type template parameter is intepreted as a series of character
literals, each representing one character from the string (in order)
and becoming a separate template parameter, with a final '\0' as the
last parameter (so that the number of resultant character literals is
one greater than the number of characters in the string literal)." and
add some appropriate example. Probably didn't get the standardese
quite right, but the point is that it is quite a minor change.
This is a good idea. It's simple and maintains backwards-
compatibility. I don't know for sure, but I do not see this taking a
lot of extra work from implementors. It also makes writing code about
three times easier. I wholly endorse this proposal (not that my
endorsement probably means much).
Sean Hunt
> > I find his extension proposal to allow a string-literal
> > as an alternative argument of variadic non-type templates
> > (of character type) quite interesting. This is IMO the
> > first approach, where I would see any chance of acceptance
> > on implementors side.
>
> Yeah. This is a good idea. It doesn't take a lot of wording either:
>
> Sean Hunt
>
It is also desirable to have a way to reconstruct string literal from
variadic non-type template of character type. maybe like:
template < char ... s >
const char* a = { s };
> It is also desirable to have a way to reconstruct string literal from
> variadic non-type template of character type. maybe like:
There is no need for language support for this.
It's already easy to achieve with templates.
I agree that this is a great idea and, although I am no language lawyer,
the proposed wording seems a very good base to start with.
I would leave out the '\0' terminator for several reasons: 1) for
consistency with the extensible literal proposal, 2) because the list of
characters is not stored in memory, so it won't be passed to functions
expecting a null-terminated string anyway, 3) a null terminator can
easily be appended, but removing it requires non-trivial
meta-programming, 4) applying the sizeof... operator to the argument
pack would return the intuitively correct length of the literal.
I also don't find it compelling to require that the string literal
appears as the last argument. Although I understand the intent, I don't
think the requirement provides a true simplification for the
implementor, yet it may limit some possibly valid uses. Moreover, if we
find the proper wording, we might even allow string literals to match
non-variadic templates. For example, consider a library component
implementing a FourCC (http://en.wikipedia.org/wiki/Fourcc):
template <char A, char B, char C, char D> class FourCC
FourCC<"RIFF"> riff; // ok: maps to FourCC<'R', 'I', 'F', 'F'>
isn't that neat? Of course, FourCC<"RIF"> and FourCC<"RIFFF"> would be
ill-formed. The key is to simply replace the literal with the sequence
of single characters and then apply the "normal" template machinery.
What do you think?
Ganesh
The draft already provides a syntax for that, it is:
template <char... s>
class S
{
const char a[sizeof...(s)];
};
template <char... s>
const char S<s>::a[sizeof...(s)] = { s... };
In another post of mine I proposed to leave out the final '\0' from the
char sequence. In that case we would have to add it, like this:
template <char... s>
class S
{
const char a[sizeof...(s) + 1];
};
template <char... s>
const char S<s>::a[sizeof...(s) + 1] = { s..., '\0' };
not a big deal.
Ganesh
User-defined literals receive either a C-string *or* a template argument
pack. The template argument pack is easily manipulatable at compile time
without introducing inefficiencies.
>
>> If yes, what are technical reasons from preventing that?
>
> None really.
> It just seems people working on the standard are not that interested
> in compile-time computation.
Given that the template argument pack possibility is explicitly provided
by proposal, how can you say that?
Ganesh
Template form ie. 'raw-form operator', is not allowed for string
literals. Otherwise my proposal wouldn't obviously make any sense...
Piotr Rak
I completely agree that it would probably be the most natural
approach to map the string literal without the zero-terminator
to the variadic character sequence.
> I also don't find it compelling to require that the string literal
> appears as the last argument. Although I understand the intent, I don't
> think the requirement provides a true simplification for the
> implementor, yet it may limit some possibly valid uses. Moreover, if we
> find the proper wording, we might even allow string literals to match
> non-variadic templates. For example, consider a library component
> implementing a FourCC (http://en.wikipedia.org/wiki/Fourcc):
>
> template <char A, char B, char C, char D> class FourCC
>
> FourCC<"RIFF"> riff; // ok: maps to FourCC<'R', 'I', 'F', 'F'>
>
> isn't that neat? Of course, FourCC<"RIF"> and FourCC<"RIFFF"> would be
> ill-formed. The key is to simply replace the literal with the sequence
> of single characters and then apply the "normal" template machinery.
I think that this extension proposal goes to far
and that there exist an alternative given concepts
to realize the same thing.
The problem I see is, that this approach might seem
natural for human tolerant pattern matching, but it
is not so well-situated for the compiler. It seems
natural for human beings, because it bases on some
form of convention: "Just assume that all template
parameters are non-type parameters and each one has
the same type and this type must be a character type".
If I understand the current state of the concept proposal
correctly it should be realizable via a *constrained*
variadic template:
#include <concepts>
template <char... s>
requires std::True<sizeof...(s) == 4>
class FourCC
{
//...
};
The enforcement to use a non-type variadic template
is simple to check for the compiler, because this
form already guarantees a homogeneous sequence.
Greetings from Bremen,
Daniel
Is there not a way to achive somthing very similar already within c+
+0x? I am thinking of using the
return type of the variadic template form of the literal operator
(obtained via decltype) as template argument.
template <char...> class A { };
template <char...Values> unsigned A<Values> operator"B"();
template <typename AT>
class CharSeq
{...};
typedef CharSeq<decltype("catch"B)> CatchKeyword;
not sure whether this works... any comments welcome.
David
Maybe my exposition was a bit confused. What I meant was only that a
string literal argument is to be replaced with a sequence of character
literal arguments *before* trying to match template argument with
template parameters. That's a simple process that any compiler could do.
So, for example:
FourCC<"RIF"> is interpreted as FourCC<'R','I','F'>
FourCC<"RIFF"> is interpreted as FourCC<'R','I','F','F'>
FourCC<"RIFFF"> is interpreted as FourCC<'R','I','F','F','F'>
the first and third template-ids are ill-formed simply because normal
template parameter matching rules make them so. No additional rule is
needed to get this result. Do you see any problem with that?
On the other hand, if I understand it correctly, the OP's proposal
requires that a string literal argument shall match *only* a template
parameter pack. This has a both advantages and disadvantages, in my opinion.
> If I understand the current state of the concept proposal
> correctly it should be realizable via a *constrained*
> variadic template:
>
> #include <concepts>
>
> template <char... s>
> requires std::True<sizeof...(s) == 4>
> class FourCC
> {
> //...
> };
>
> The enforcement to use a non-type variadic template
> is simple to check for the compiler, because this
> form already guarantees a homogeneous sequence.
This solution is correct and valid, however there's no need for concepts
to tackle this particular example with my approach.
Just my opinion,
Ganesh
I think that is not a problem, am I missing something obvious?
So far i was not able to construct example when proposed aproach would
be overly expensive. It tends to be rather simple tree subsitution.
Compiler logic needed for that is already present
to handle variadic argument pack expansion.
I have made hackish implementation of this, which includes
Alberto Ganesh Barbati extension to proposal, for gcc compiler.
It still needs some `love'. Maybe soon i will find real time to work
on that.
It seems that my orginal proposal is slightly harder to implement (in
gcc), one would have to check just if there is parameter pack in
template parameter list too.
Following example shows status of this patch (and it Works For Me TM):
#include <iostream>
template <char... Chars_>
struct Foo {
static const char chars[sizeof...(Chars_)+1];
};
template <char...Chars_>
const char
Foo<Chars_...>::chars[sizeof...(Chars_)+1] = {Chars_...};
template <char B_, char A_, char R_, char Term_>
struct Bar
{
static const char chars[4];
};
template <char B_, char A_, char R_, char Term_>
const char
Bar<B_, A_, R_, Term_>::chars[4] = {B_, A_, R_, Term_};
int main()
{
std::cout << Foo<"foo", '\0'>::chars << std::endl;
std::cout << Bar<"bar", '\0'>::chars << std::endl;
}
Compile with -std=c++0x -fstring-template-arguments
The know deficiencies are:
- doesn't handle wide literals (should be easy),
and unicode literals (not in gcc yet)
- I should report error in case of "" or L""
- definitly needs testing (DejaGNU here I come!)
- and documentation...
But overall, it should be enough to see how it feels.
I am not sure if default template arguments should be supported ie:
template <char... Chars_ = "Oink!">
struct Foo;
Comments welcome :)
Note that, this was first time i've seen gcc sources...
For brave people, patch against gcc trunk, revision 134411
http://doppler.no-ip.org/~prak/fstring-template-arguments.patch
Piotr Rak
That is great! It's really a good thing what you've done.
> It seems that my orginal proposal is slightly harder to implement (in
> gcc), one would have to check just if there is parameter pack in
> template parameter list too.
That's what I was afraid about, when I wrote about "advantages and
disadvantages" in my previous post.
>
> Following example shows status of this patch (and it Works For Me TM):
>
> #include <iostream>
>
> template <char... Chars_>
> struct Foo {
> static const char chars[sizeof...(Chars_)+1];
> };
>
> template <char...Chars_>
> const char
> Foo<Chars_...>::chars[sizeof...(Chars_)+1] = {Chars_...};
>
> template <char B_, char A_, char R_, char Term_>
> struct Bar
> {
> static const char chars[4];
> };
>
> template <char B_, char A_, char R_, char Term_>
> const char
> Bar<B_, A_, R_, Term_>::chars[4] = {B_, A_, R_, Term_};
> int main()
> {
> std::cout << Foo<"foo", '\0'>::chars << std::endl;
> std::cout << Bar<"bar", '\0'>::chars << std::endl;
> }
>
> Compile with -std=c++0x -fstring-template-arguments
Very nice! Very. I like the idea of being able to concatenate string and
character literals in a template argument list.
>
> The know deficiencies are:
> - doesn't handle wide literals (should be easy),
> and unicode literals (not in gcc yet)
I guess the simplest thing is to replace the literal with a sequence of
char, char16_t, char32_t or wchar_t according to the string literal and
let the usual promotion and conversion machinery to happen. Were you
think of something different?
> - I should report error in case of "" or L""
Do we need to diagnose an error in this situation? Would expanding to an
empty sequence be impossible or unreasonable?
> - definitly needs testing (DejaGNU here I come!)
If you need help, please contact me privately.
> - and documentation...
If you need help, please contact me privately.
> But overall, it should be enough to see how it feels.
>
> I am not sure if default template arguments should be supported ie:
>
> template <char... Chars_ = "Oink!">
> struct Foo;
>
> Comments welcome :)
Ah! Good point. Currently default template-arguments cannot be specified
for parameter packs. Although the feature is very appealing, I would
leave it at that. Unless we make that a very special case, we would
actually be forced to provide a meaning for the "equivalent" syntax:
template <char... Chars_ = 'O','i','n','k','!'>
struct Foo;
and this would open a Pandora's box, IMHO.
So I guess we should provide wording to disallow literals in default
template-arguments, where replacement doesn't make sense.
>
> Note that, this was first time i've seen gcc sources...
That means gcc sources are very well written or that you are very
skilled or both ;)
> For brave people, patch against gcc trunk, revision 134411
> http://doppler.no-ip.org/~prak/fstring-template-arguments.patch
Thanks! Now it's time to prepare a formal proposal. Let me help you with
that.
Ganesh
Default arguments aren't permitted on variadic parameters,
unfortunately, so the question is moot.
> Comments welcome :)
>
> Note that, this was first time i've seen gcc sources...
Well, you certainly did better than I would have... that looks like a
solid patch, but in reality I'm deathly affraid of the GCC sources.
This is very good that you've made this patch; it means that we are
very likely to be able to get this into C++0x, and if not, then as a
GCC extension. You should try and see if you can get this into the
next release (I'm not experienced enough with GCC development to tell
you how to do that).
> For brave people, patch against gcc trunk, revision 134411http://doppler.no-ip.org/~prak/fstring-template-arguments.patch
>
> Piotr Rak
Awesome!
Sean Hunt
> Piotr Rak ha scritto:
>>
>> - I should report error in case of "" or L""
>
> Do we need to diagnose an error in this situation? Would expanding to
> an empty sequence be impossible or unreasonable?
I think that this also depends on how you intend to handle cases like
this:
template <char c> T:
T<"", "", 'a', "", ""> aCharacter:
std::vector<int, ""> MyVec:
My call would be that an empty string-literal is disallowed if it is not
used in the context of a parameter-pack of a variadic template.
I don't know enough about the details of variadic templates to give a
firm standpoint on how to deal with empty string-literals for
parameter-packs. My initial feeling is that if empty parameter-packs
are fully defined, then it should be possible to use empty
string-literals in that context (with an expansion to an empty
parameter-pack).
>
> Ganesh
>
Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
It is probably too late for proposing a stand alone addition to the
committee, but if you could reduce the amount of wording needed to
specify this extension as much as possible, maybe you can have some
one (like the original author of variadic templates, IIRC it was
Douglas Gregor), to sneak it to the committee as an 'obivious small
fix' to what has already been accepted.
Good luck, I think that this would be a great addition to the standard
(Yay for real embedded DSLs!).
(BTW, the patch is impressively small, great job!)
--
Giovanni P. Deretta
like:
template <char... Chars_ = 'O', 'i', 'n', 'k'> // Looks odd
struct Foo;
Or there is other reasoning after that?
I don't see any problem with my syntax, it feels rather natural for
me.
Problem i see, is more like: "Why character types should be `better'
that for example int?"
Anyway, having this is not essential...
Piotr
On Apr 18, 2:13 pm, Sean Hunt <ride...@gmail.com> wrote:
> On Apr 17, 7:35 pm, Piotr Rak <piotr....@gmail.com> wrote:
>
> Well, you certainly did better than I would have... that looks like a
> solid patch, but in reality I'm deathly affraid of the GCC sources.
>
> This is very good that you've made this patch; it means that we are
> very likely to be able to get this into C++0x, and if not, then as a
> GCC extension. You should try and see if you can get this into the
> next release (I'm not experienced enough with GCC development to tell
> you how to do that).
>
This is not ready for inclusion yet.
I will aim to do that in near future though, however it would be nice
if atleast formal proposal was written before that.
Thanks, for your feedback :)
Cheers! Piotr
However:
template <char...> class Foo;
Foo<""> foo; // == Foo<> foo, Ok
//but:
Foo<"","",""> foo2; // is that Ok?
//also:
template <char> class Bar;
Bar<'a', ""> bar; // is it Ok?
It might be feature, in some cases, maybe some automated tool dumps ""
fo empty strings...
But i consider this code bit confusing, matter of taste...
So simplest solution would be just ban "".:)
Note that current version of patch has bug and will behave bad if
there is "" as template arguemnt, be warned!
> > - definitly needs testing (DejaGNU here I come!)
>
> If you need help, please contact me privately.
>
> > - and documentation...
>
> If you need help, please contact me privately.
>
> > But overall, it should be enough to see how it feels.
>
Any help is highly welcome, I'll do that soon, thanks! :)
> > I am not sure if default template arguments should be supported ie:
>
> > template <char... Chars_ = "Oink!">
> > struct Foo;
>
> > Comments welcome :)
>
> Ah! Good point. Currently default template-arguments cannot be specified
> for parameter packs. Although the feature is very appealing, I would
> leave it at that. Unless we make that a very special case, we would
> actually be forced to provide a meaning for the "equivalent" syntax:
>
> template <char... Chars_ = 'O','i','n','k','!'>
> struct Foo;
>
> and this would open a Pandora's box, IMHO.
>
> So I guess we should provide wording to disallow literals in default
> template-arguments, where replacement doesn't make sense.
Equivalent syntax is odd IMO, so that is good point.
I am not keen of providing special cases where we would allow syntax
with "", but disallow other one.
Also there is no syntax for non-character types, which would make this
feature 'asymmetric' in a language.
This is not essential, maybe we just should leave that out?
>
> > Note that, this was first time i've seen gcc sources...
>
> That means gcc sources are very well written or that you are very
> skilled or both ;)
>
I think the truth is, that sources are well documented, and
implementation of this feature was really trivial. :)
Almost half of patch is command line handling.
>
>
> Thanks! Now it's time to prepare a formal proposal. Let me help you with
> that.
>
Are you reading my mind?
In fact I was hoping, that someone will offer help with that.
My poor language skills could otherwise hurt this proposal. :)
Thanks again, for all your feedback and involvment. :)
Piotr