我定义了以下模板,以便我可以执行显式但安全的强制转换:
/// cast using implicit conversions only
template <class To,class From>
inline To safe_cast( const From &from ) {return from;}
经常(例如,当将参数传递给 sprintf 和类似函数时)我想使用这个模板来执行从字符串类到 c 样式字符串的转换。但是,它表明当临时被传递时这是不可能的,因为临时不会活得足够长。
考虑以下示例:
class Object
{
public:
MyStringClass GetDebugName() const;
};
Object obj;
printf("%s",safe_cast<const char *>(obj.GetDebugName()));
来自 obj.GetDebugName() 的临时对象仅在 safe_cast 期间存在,并且在 printf 内部时指针无效(指向已被销毁的临时字符串的数据)。
作为一种解决方法,我目前使用没有模板调用的直接强制转换:const char *c = (const char *)(obj.GetDebugName()
,但这有一个缺点是类型安全性降低,因为强制转换不必要地强(例如,即使 obj.GetDebugName() 返回 int 而不是一个字符串值)。static_cast
可能会稍微好一点,但即使这样也太强了,我想在任何情况下都不能保证安全时出错。
1)如果我没记错的话,标准说临时生命周期是一个声明(除非通过绑定到 const 引用来扩展,在这种情况下它是引用的生命周期)。查看上面的 printf 示例时,我不太确定“语句”是什么,以及我看到的行为是否符合要求。如果语句是整个 printf,则 const From &from 的生命周期会更短——我应该期望临时的生命周期是多少?有人可以澄清吗?
2) 是否有其他方法可以进行安全的转换,但结果的寿命足够长而有用?
编辑:
请考虑一下这更像是一种一般性问题,我正在寻找一种机制,如何针对临时生命周期进行这样的转换,我对任何特定字符串类的特殊情况不太感兴趣。
澄清为什么我不想使用 .c_str 或类似的成员函数:我希望转换代码与类型无关,我不希望代码依赖于我知道这个特定字符串类型已实现 c_str 的事实,我即使 ObjectDebugName 将返回不同的字符串类,或者即使 ObjectDebugName 已经返回 const char *(这排除了调用 .operator const char *() 的可能性,也希望它能够工作。