views:

92

answers:

1

I have the following code, which uses a Unicode string class from a library that I'm writing:

#include <cstdio>
#include "ucpp"
main() {
  ustring a = "test";
  ustring b = "ing";
  ustring c = "- -";
  ustring d;
  d = "cafe\xcc\x81";
  printf("%s\n", (a + b + c[1] + d).encode());
}

The encode method of the ustring class instances converts the internal Unicode into a UTF-8 char *. However, because I don't have access to the char class definition, I am unsure on how I can define an implicit typecast (so that I don't have to manually call encode when using with printf, etc).

+5  A: 

First, I would recommend that you consider not providing an implicit conversion. You may find that the situations where unexpected conversions are not caught as errors outweighs the cost of calling encode when you want a char*.

If you do decide to provide an implicit conversion you declare it like this (inside your class definition.

operator char*();

You might be able to make the method const, in which case you can use:

operator char*() const;

Usually you would also want to return a pointer to a non-modifiable buffer:

operator const char*() const;

In the body of your function you should return an appropriate pointer. As an implicit conversion clients wouldn't expect to have to free the returned buffer so if you need to make a special buffer for your return value you will have to maintain a pointer to this buffer until a suitable point to free it. Typically such a suitable moment might be the next mutating operation on your class object.

Note that as printf takes any number and type of optional arguments you would still need to cast your class object in any case.

printf("%s\n", static_cast<const char*>(a + b + c[1] + d));

or

printf("%s\n", (const char*)(a + b + c[1] + d));

Both of these are more verbose than an explicit call to encode.

Charles Bailey
+1 Much better explanation than mine :)
AraK
Thank you very much for the advice. I will think about the pros/cons and test out whether an implicit is really beneficial.
Delan Azabani
(Sorry about not accepting your answer yet; SO is limiting my acceptance frequency so I have to wait a few minutes)
Delan Azabani
@Delan Azabani: You don't have to accept answers straight away; it's fine to wait an see if someone comes up with a better answer that mine.
Charles Bailey
For string classes especially, an implicit conversion to `char*` is very problematic. Even something simple as `str[i]` will now probably become ambiguous. Similar for `c ? str : "foo"`.
Johannes Schaub - litb
The implicit conversion will not be invoked for `printf` in the first place, because this function accepts any type you throw at it. So you are already losing the battle...
UncleBens
@UncleBens: I never realised that! Hmm... maybe the implicit would be invoked when using puts()?
Delan Azabani
@UncleBens: Good point about this particular situation; I'll add to my answer.
Charles Bailey
For outputting, isn't it better to provide the relevant ostream overrides, rather than using C-style I/O functions? (I'm a C++ noob)
dreamlax
@dreamlax: I think one would definitely expect a C++ string class to overload `<<` and `>>` (and getline).
UncleBens
@dreamlax: If you provide a function that returns a null-terminated `const char*` then you can use `%s` and `printf` or iostream's native `const char*` `operator<<` or any other io library without writing io specific code. If you can get away with a more general solution with less code then so much the better.
Charles Bailey
One other alternative is to let it implicitly convert by doing `printf("%s\n", +(a + b + c[1] + d));`
Johannes Schaub - litb
@litb: I hadn't thought of that. Yes, it would be less verbose but in itself it looks like another strong argument against an implicit conversion :) .
Charles Bailey