Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Overloading string literal

102 views
Skip to first unread message

qak

unread,
May 12, 2013, 10:50:57 AM5/12/13
to
Suppose: int Buffer::Put(const char *s);
Where: Put() has to find the length of 's' by strlen().
I would like to have: Put("Header Tag...") where sizeof("Header Tag...") -
1 is known at compile-time.
Macro is acceptable, but must report error if 's' is not string literal:
sizeof(s) yield size of const char*, which is not length of string.

Marcel Müller

unread,
May 12, 2013, 11:02:03 AM5/12/13
to
On 12.05.13 16.50, qak wrote:
> Suppose: int Buffer::Put(const char *s);
> Where: Put() has to find the length of 's' by strlen().
> I would like to have: Put("Header Tag...") where sizeof("Header Tag...") -
> 1 is known at compile-time.

#include <stdio.h>

template <size_t len>
void put(const char (&str)[len])
{ printf("%u, ", len);
fwrite(str, len, 1, stdout);
putchar('\n');
}

int main()
{ put("Test1");
put("test2\0test");
return 0;
}


Marcel

qak

unread,
May 13, 2013, 11:24:38 AM5/13/13
to
Marcel Müller <news.5...@spamgourmet.org> wrote in news:518faeec$0
$6574$9b4e...@newsspool3.arcor-online.net:

> #include <stdio.h>
>
> template <size_t len>
> void put(const char (&str)[len])
> { printf("%u, ", len);
> fwrite(str, len, 1, stdout);
> putchar('\n');
> }
>
> int main()
> { put("Test1");
> put("test2\0test");
> return 0;
> }
>

Many thanks, works perfectly for me

#include <stdio.h>

template <size_t len>
void put(const char (&str)[len])
{
printf("%u, ", len);
fwrite(str, len, 1, stdout);
putchar('\n');
}

int main()
{
const char Test[] = "TEST";
const char *Test2 = "TEST2";
put(Test);
put(Test2); // error C2784: 'void put(const char (&)[len])' :
could not deduce template argument for 'const char (&)[len]' from 'const
char *'

Paavo Helde

unread,
May 13, 2013, 11:52:57 AM5/13/13
to
qak <q...@mts.net.NOSPAM> wrote in news:XnsA1BF6A0FDEAA1qkieumtsnet@
94.75.214.39:
>
> #include <stdio.h>
>
> template <size_t len>
> void put(const char (&str)[len])
> {
> printf("%u, ", len);

%u is wrong here, the type of len is size_t.

What's wrong with std::cout? C-style printf() is quite dangerous,
especially if you don't know how to use it.


> fwrite(str, len, 1, stdout);

This outputs also the zero terminator, not sure if this was the intention.

hth
Paavo

Marcel Müller

unread,
May 13, 2013, 12:12:28 PM5/13/13
to
On 13.05.2013 17:52, Paavo Helde wrote:
> qak <q...@mts.net.NOSPAM> wrote in news:XnsA1BF6A0FDEAA1qkieumtsnet@
> 94.75.214.39:
>>
>> #include <stdio.h>
>>
>> template <size_t len>
>> void put(const char (&str)[len])
>> {
>> printf("%u, ", len);
>
> %u is wrong here, the type of len is size_t.

Well, my old compiler does not know about the size type place holder.

> What's wrong with std::cout? C-style printf() is quite dangerous,
> especially if you don't know how to use it.

cout code looks like crap, if there are multiple parameters or explicit
format specifiers involved. And for this simple example it simply makes
no difference.

The API looks to me like someone wanted to demonstrate what could be
done with operator overloading in C++ in the early 90's.

>> fwrite(str, len, 1, stdout);
>
> This outputs also the zero terminator, not sure if this was the intention.

True. This was intended, to demonstrate what happens if one takes the
raw literal. The \0 may not show up on every shell, but at least the len
tells it's existence.


Marcel

Paavo Helde

unread,
May 13, 2013, 12:47:52 PM5/13/13
to
=?ISO-8859-15?Q?Marcel_M=FCller?= <news.5...@spamgourmet.com> wrote
in news:519110ed$0$6568$9b4e...@newsspool3.arcor-online.net:

> On 13.05.2013 17:52, Paavo Helde wrote:
>> qak <q...@mts.net.NOSPAM> wrote in news:XnsA1BF6A0FDEAA1qkieumtsnet@
>> 94.75.214.39:
>>>
>>> #include <stdio.h>
>>>
>>> template <size_t len>
>>> void put(const char (&str)[len])
>>> {
>>> printf("%u, ", len);
>>
>> %u is wrong here, the type of len is size_t.
>
> Well, my old compiler does not know about the size type place holder.

Then you need to cast len to a supported type. As it stands, it is UB and
may fail to work in 64-bit programs. Actually it might appear to work on
little-endian computers, but only with the last argument.

>> What's wrong with std::cout? C-style printf() is quite dangerous,
>> especially if you don't know how to use it.
>
> cout code looks like crap, if there are multiple parameters or
> explicit format specifiers involved. And for this simple example it
> simply makes no difference.

If it makes no difference one should prefer code which is easier to write
correctly and does not cause UB. Also, you may want to look up
boost::format (not sure if it was included in C++11 or not).

Cheers
Paavo

Juha Nieminen

unread,
May 14, 2013, 3:24:01 AM5/14/13
to
Marcel M?ller <news.5...@spamgourmet.com> wrote:
> cout code looks like crap, if there are multiple parameters or explicit
> format specifiers involved. And for this simple example it simply makes
> no difference.

Actually it makes a difference, given that %u may expect a 32-bit value
and size_t may be 64-bit.

How would you use printf in a situation like this?

template<typename T>
void foo(T value)
{
std::printf("???", value);
}

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Andy Champ

unread,
May 14, 2013, 6:31:23 AM5/14/13
to
On 14/05/2013 08:24, Juha Nieminen wrote:
> Marcel M�ller <news.5...@spamgourmet.com> wrote:
>> cout code looks like crap, if there are multiple parameters or explicit
>> format specifiers involved. And for this simple example it simply makes
>> no difference.
>
> Actually it makes a difference, given that %u may expect a 32-bit value
> and size_t may be 64-bit.
>
> How would you use printf in a situation like this?
>
> template<typename T>
> void foo(T value)
> {
> std::printf("???", value);
> }
>

template <> void foo(size_t value)
{
std::printf("%zd", value);
}

Andy

Juha Nieminen

unread,
May 16, 2013, 4:05:59 AM5/16/13
to
Andy Champ <no....@nospam.invalid> wrote:
>> How would you use printf in a situation like this?
>>
>> template<typename T>
>> void foo(T value)
>> {
>> std::printf("???", value);
>> }
>>
>
> template <> void foo(size_t value)
> {
> std::printf("%zd", value);
> }

And you repeat that for every single type that std::printf supports,
now and in the future?

Öö Tiib

unread,
May 16, 2013, 6:52:00 AM5/16/13
to
On Thursday, 16 May 2013 11:05:59 UTC+3, Juha Nieminen wrote:
> Andy Champ <no....@nospam.invalid> wrote:
> >> How would you use printf in a situation like this?
> >>
> >> template<typename T>
> >> void foo(T value)
> >> {
> >> std::printf("???", value);
> >> }
> >>
> >
> > template <> void foo(size_t value)
> > {
> > std::printf("%zd", value);
> > }
>
> And you repeat that for every single type that std::printf supports,
> now and in the future?

I think we should have C++ printf. If for nothing else then just to silence that
boring argument. Something like in Java or like boost::format would eventually
calm it down. With variadic templates we have all the tools we need for making
type-safe printf.

James Kanze

unread,
May 16, 2013, 11:06:53 AM5/16/13
to
There's no need for variadic templates; Boost already has
boost::format (although it makes the disasterous choice of % as
the formatting operator), and long be fore that, I'd implemented
a Format class.

I suspect that the reason it doesn't make it into the standard
is that there's really no use for them. The native ostream is
more intuitive and easier to use.

--
James

Öö Tiib

unread,
May 16, 2013, 9:54:33 PM5/16/13
to
On Thursday, 16 May 2013 18:06:53 UTC+3, James Kanze wrote:
> On Thursday, May 16, 2013 11:52:00 AM UTC+1, Öö Tiib wrote:
> > I think we should have C++ printf. If for nothing else then
> > just to silence that boring argument. Something like in Java
> > or like boost::format would eventually calm it down. With
> > variadic templates we have all the tools we need for making
> > type-safe printf.
>
> There's no need for variadic templates; Boost already has
> boost::format (although it makes the disasterous choice of % as
> the formatting operator), and long be fore that, I'd implemented
> a Format class.

Yes, what I meant was that with variadic templates it can look more
natural than boost::format but still have same type-safety and
support to user-defined types.

> I suspect that the reason it doesn't make it into the standard
> is that there's really no use for them. The native ostream is
> more intuitive and easier to use.

People make and use alternatives like 'QString("%1 %2").arg(a).arg(b)'
or 'boost::format("%1% %2%") % a % b' so it must be is attractive and
elegant for their taste.

Gerhard Fiedler

unread,
May 21, 2013, 5:57:39 AM5/21/13
to
Besides, it's very inconvenient to use std::ostream for
internationalization (the position of embedded runtime values may change
with the output language). You need something like boost::format to do
that nicely.

Gerhard

James Kanze

unread,
May 21, 2013, 7:20:52 AM5/21/13
to
On Tuesday, May 21, 2013 10:57:39 AM UTC+1, Gerhard Fiedler wrote:
There's nothing surprising going on here. Things like QString
or boost::format are just imitating something which sounded like
a good idea at the time. (The X/Open extensions to printf.) In
the meantime, those of us who had access to the original and
could actually try to use it realized that it wasn't such a good
idea after all. If you're trying to handle multilingual output,
neither the printf extensions nor any of its imitators help.
The difference between languages goes way beyond the order in
which you embed runtime values: you need to modify words
depending on singular or plural (or dual), or the word order
depends on the actual words, and any number of other issues. In
the end, you have to write a separate DLL for each language, or
you end up compromizing.

--
James
0 new messages