Question

I have a following template defined so that I can perform an explicit, but safe cast:

/// cast using implicit conversions only
template <class To,class From>
inline To safe_cast( const From &from ) {return from;}

Frequently (e.g. when passing arguments into sprintf and similar functions) I would like to use this template to perform a conversion from a string class to a c-style string. However, it shows this is not possible when temporary is passed, because the temporary will not live long enough.

Consider following example:

class Object
{
  public:
  MyStringClass GetDebugName() const;
};

Object obj;
printf("%s",safe_cast<const char *>(obj.GetDebugName()));

The temporary from obj.GetDebugName() lives only during the safe_cast and the pointer is invalid (points to the data of the string temporary which has already been destroyed) when inside of the printf.

As a workaround I a currently using direct cast without a template call: const char *c = (const char *)(obj.GetDebugName(), but this has a drawback of reduced type safety, as the cast is unnecessarily strong (e.g. it would silently succeed even if obj.GetDebugName() would be returning int instead of a string value). static_cast might be slightly better, but even that is too strong, I would like to get an error on any situation where cast is not sure to be safe.

1) If I am not mistaken, the standard says the temporary life time is a statement (unless extended by being bound to a const reference, in which case it is the life time of the reference). When looking at the printf example above, I am not quite sure what a "statement" is, and if the behaviour I have seen is conformant or not. If the statement is the whole printf, the lifetime of the const From &from is shorter - what lifetime should I expect from the temporary? Can someone clarify?

2) Is there some other way to make a conversion which would be safe, but the result would live long enough to be useful?

Edit:

Please, consider this more a kind of general question, I am seeking for a mechanism how can a conversion like this to be done with regard to the temporary lifetime, I am not that much interested in a special case of any particular string class.

To clarify why I do not want to use .c_str or a similar member function: I would like the conversion code to be type agnostic, I do not want the code to rely on the fact I know this particular string type has c_str implemented, I want it to work even if a different string class would be returned by ObjectDebugName, or even if ObjectDebugName would be already returning const char * (which excludes the possibility of calling .operator const char *().

Was it helpful?

Solution

I can perform an explicit, but safe cast

I would call it an implicit cast done explicitly, or just and explicit implicit cast.

1) If I am not mistaken, the standard says the temporary life time is a statement (unless extended by being bound to a const reference, in which case it is the life time of the reference). When looking at the printf example above, I am not quite sure what a "statement" is, and if the behaviour I have seen is conformant or not. If the statement is the whole printf, the lifetime of the const From &from is shorter - what lifetime should I expect from the temporary? Can someone clarify?

You are correct, the temporary is destroyed after printf've returned. The code you provided should work. If it doesn't, it means that you misprovided some important information.

OTHER TIPS

I don't know why you are using your own string class here. Does the class have a member function to get the const char * out of it?

std::string GetDebugName();

printf( "%s", GetDebugName().c_str() );

would be safe as the temporary would remain valid during that statement, for example.

You can call the conversion function directly:

printf("%s", obj.GetDebugName().operator const char*());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top