Default conversion when passing to an ellipsis

K

Kufa

Hi,

I have a class String which implements the const char*() operator. I
was doing some tests today and did something like:
String test( "hello world" );
printf( "%s\n", test ); // instead of test.c_str(); or (const
char*)test

This code compiled and worked fine on a x86/visual studio 7.1. On some
other platforms, gcc was giving errors, as i would expect.

So i'm wondering if visual studio is allowing something which is
forbidden by the standard, or is there a way to force a default
conversion operator to be called when an object instance is passed to
an ellipsis?

Thanks,

/d
 
V

Victor Bazarov

Kufa said:
I have a class String which implements the const char*() operator. I
was doing some tests today and did something like:
String test( "hello world" );
printf( "%s\n", test ); // instead of test.c_str(); or (const
char*)test

This code compiled and worked fine on a x86/visual studio 7.1. On some
other platforms, gcc was giving errors, as i would expect.

So i'm wondering if visual studio is allowing something which is
forbidden by the standard, or is there a way to force a default
conversion operator to be called when an object instance is passed to
an ellipsis?

If you need Visual-C++-specific information, please consider asking
in 'microsoft.public.vc.language'.

Since 'String' here is an object, passing it to a function with the
ellipsis causes undefined behaviour (5.2.2/7).

V
 
A

Andrey Tarasevich

Kufa said:
...
I have a class String which implements the const char*() operator. I
was doing some tests today and did something like:
String test( "hello world" );
printf( "%s\n", test ); // instead of test.c_str(); or (const
char*)test

This code compiled and worked fine on a x86/visual studio 7.1. On some
other platforms, gcc was giving errors, as i would expect.

So i'm wondering if visual studio is allowing something which is
forbidden by the standard, or is there a way to force a default
conversion operator to be called when an object instance is passed to
an ellipsis?
...

Neither. Strictly speaking, class types are allowed as arguments for
'...' parameters, meaning that this particular piece of code is
well-formed and no diagnostics is required. However, with class types
the behavior is defined only when the class type is a POD. Your class
type is clearly not a POD, which means that the behavior is undefined.

From that point of view, VS compiler is doing nothing wrong. It is not
required to generate a diagnostic message and it is allowed to do
interpret the code in any way it pleases.
 
P

Phlip

Kufa said:
I have a class String which implements the const char*() operator. I was
doing some tests today and did something like: String test( "hello world"
);
printf( "%s\n", test ); // instead of test.c_str(); or (const char*)test

The test object drops in as an object; a copy of it appears in printf's
stack's arguments.

If your string class starts with char *, then %s will accidentally see the
address of your string, which it expects. This is still undefined behavior.

(Interestingly, Microsoft's CString class was tweaked to permit
programmers to pass it like this. Such behavior lies between undefined and
implementation-defined. MS gave up trying to educate programmers not to
pass strings into ellipses like that.)

Don't pass strings into ellipses like that.
This code compiled and worked fine on a x86/visual studio 7.1. On some
other platforms, gcc was giving errors, as i would expect.

So i'm wondering if visual studio is allowing something which is forbidden
by the standard, or is there a way to force a default conversion operator
to be called when an object instance is passed to an ellipsis?

It's just undefined behavior, so it may appear to work in some situations.

In general, ... arguments are evil, and the printf() family of functions
shouldn't be used without great need. Get down with operator<< and
<iostream>, and you can do nearly all your formatting needs. All more
typesafe than .... Your ultimate problem was VC++ did not emit a warning
when it saw %s not matched with a char *. Some compilers can warn like
that, as a custom extension.

(If you can figure out the iomanipulators!)
 
B

Bo Persson

Kufa said:
Hi,

I have a class String which implements the const char*() operator. I
was doing some tests today and did something like:
String test( "hello world" );
printf( "%s\n", test ); // instead of test.c_str(); or (const
char*)test

This code compiled and worked fine on a x86/visual studio 7.1. On
some
other platforms, gcc was giving errors, as i would expect.

So i'm wondering if visual studio is allowing something which is
forbidden by the standard, or is there a way to force a default
conversion operator to be called when an object instance is passed
to
an ellipsis?

You are not allowed to pass a class object thru an ellipsis. If you
do, the compiler is allowed to do whatever it likes.


The CString class in VS7.1 does its trick by having the class object
contain a char* pointer only. That way printf cannot tell the
difference between a raw pointer and a class containing the pointer!


Bo Persson
 
A

Andrey Tarasevich

Andrey said:
...
Your class type is clearly not a POD, which means that the behavior is undefined.
...

Oops.... I kind of assumed that your class in not a POD, but I don't
really know that. Even though have a conversion operator in your class,
it still can be a POD, meaning that the behavior might still be defined
as far as we are talking about supplying arguments for '...' parameters.

However, even if your type is a POD, it still will be passed as a class
object (as a whole, that is). No conversion to 'char*' type will be
performed by the compiler. That would immediately mean that the behavior
is still undefined, but for a different reason: using '%s' format
specifier with a non-string argument.
 
A

Andrey Tarasevich

Victor said:
With a user-defined c-tor?
...

Oh, OK, thanks, I missed that part. In that case my first message was
correct. Although there are lots of valuable stuff in the second one as
well :O)
 
J

Jerry Coffin

[ ... ]
You are not allowed to pass a class object thru an ellipsis. If you
do, the compiler is allowed to do whatever it likes.

This is true only for non-POD class objects. For POD
objects, the behavior is well defined.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top