我正在研究一个需要向后兼容C ++ 03的遗留库,但也可以向前兼容以利用C ++ 11的特性,如移动语义和显式转换。
那么,是否有可能在C ++ 03中模拟显式转换?我明显知道明确的bool(或“安全”bool)习语 - 但这只是用于转换为布尔类型。是否可以在C ++ 03中模拟一般的显式强制转换操作符?
我查了一下,并在一本名为“Imperfect C++ : Practical Solutions for Real-Life Programming”的书中找到了对此的讨论。
在本书中,他们讨论了在C ++ 03中模拟显式转换的一些想法(这本书是在C ++ 11之前编写的)。最终,他们建议您创建一个explicit_cast<T>
模板。但是,我不喜欢这个解决方案,因为我希望用户能够使用static_cast<T>
,这在C ++ 11中运行良好。
因此,另一种解决方案是强制编译器执行两次转换,这将禁止隐式转换。一个例子就是:
class int_cast
{
public:
int_cast(const int& v) : m_value(v)
{ }
operator int() const
{
return m_value;
}
private:
int m_value;
};
struct Foo
{
Foo()
{
x = 10;
}
operator int_cast() const
{
return int_cast(x);
}
int x;
};
此处,Foo
应显式可转换为int
,但不能隐式。 (此代码几乎逐字逐句地从 Imperfect C ++ 中解除,除了在他们的示例中他们将自定义Time
对象转换为std::tm
。
然而,这实际上并不起作用,至少不使用GCC 4.7.2:
Foo f;
int x = static_cast<int>(f);
这导致:
test3.cpp: In function ‘int main()’:
test3.cpp:44:28: error: invalid static_cast from type ‘Foo’ to type ‘int’
所以我猜“不完美的C ++”在这里是错误的。即使使用显式强制转换,编译器也无法将Foo
转换为int
。 (也许这适用于较旧的编译器?)那么,无论如何都要在C ++ 03中模拟它(不使用自定义强制转换操作符)?
答案 0 :(得分:3)
“不完美的C ++”是对的,因为它使用自定义的“关键字” - 实际上是伪装成关键字的函数名称(不像例如:Tribool的indeterminate
)。如果你尝试static_cast
,你会遇到限制,即语言只接受涉及多达一个用户定义类型的转换链,而你有两个转换 - 从“Foo”到“int_cast”,从那里到int
。
如果你想特别能够static_cast
,那么你可能不得不用宏来破解正常static_cast
...并接受生活在未定义的行为领域。我的首选是实际work in the inverse direction:在C ++ 11模式下,只需使用explicit_cast
并使用宏将其重新定义为static_cast
调用。我在我的C ++ backports工具包中使用显式强制转换,因此在我编写的所有C ++代码中都使用了,我到目前为止找不到重要的问题。