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 *().