Question

I have a class that defined a user defined operator for a TCHAR*, like so

CMyClass::operator const TCHAR*() const
{
    // returns text as const TCHAR*
}

I want to be able to do something like

CMyClass myClass;
_tprintf(_T("%s"), myClass);

or even

_tprintf(_T("%s"), CMyClass(value));

But when trying, printf always prints (null) instead of the value. I have also tried a normal char* operator, as well variations with const etc. It only works correctly if I explicitly call the operator or do a cast, like

_tprintf(_T("%s\n"), (const TCHAR*)myClass);
_tprintf(_T("%s\n"), myClass.operator const TCHAR *());

However, I don't want to cast. How can this be achieved?

Note, that a possibility is to create a function that has a parameter of const TCHAR*, so that it forcible calls the operator TCHAR*, but this I also don't want to implement.

Was it helpful?

Solution

Avoid conversion operators. They rarely do what you want, and then explicit calls are painful. Rename operator const TCHAR*() const to TCHAR *str() const.

OTHER TIPS

The C++ Standard says that implicit conversions like this are not applied to ellipsis parameters - how would the compiler know what conversion to apply? You will have to perform the conversion explicitly yourself, or better yet stop using printf.

Conversion operators are called when the compiler wants to convert a value to another type. This works for functions that take defined parameters of specific types. It doesn't work for variadic functions like printf() with ... in the function declaration. These functions take the arguments and then work with them, so the conversion operator is never called.

To be specific, when the compiler sees printf("%s", foo), it passes foo, whatever it is, to printf(), which will have to assume it's suitable for a %s format as it is. No conversion operator will be called (although certain arithmetic promotions will take place).

Conversion operators in general cause problems. By having that operator in that class, you've complicated function overload resolution, since the compiler can interpret a CMyClass as if it were a TCHAR *. This can cause unexpected results, either causing code to compile when you really didn't want it to, or selecting the wrong overloaded function. (For example, given CMyClass cmc;, the expression cmc + 10 is suddenly legal, since TCHAR * + int is perfectly legitimate pointer arithmetic.) The usual practice is to label such conversions explicit.

Casting is the right thing to do if you want to use printf style APIs and rely on a conversion operator (and I am not going to argue here whether or not you should use these features). However, I would use static cast, e.g. _tprintf(_T("%s\n"), static_cast<const TCHAR*>(myClass));

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top