Why auto_ptr seems to breach private inheritance on Visual C++?

偶尔善良 提交于 2019-12-01 15:08:21

The Derived*-to-Base* conversion, even if the inheritance is private, is permitted in C-style and functional casts. And no, it doesn't mean reinterpret_cast in that case.

This isn't allowed by the standard, but it very nearly looks as if it is allowed, so it's a subtle bug.

5.2.3 Explicit type conversion (functional notation) [expr.type.conv]

1 [...] If the expression list is a single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (5.4). [...]

5.4 Explicit type conversion (cast notation) [expr.cast]

4 The conversions performed by

  • a const_cast (5.2.11),
  • a static_cast (5.2.9),
  • a static_cast followed by a const_cast,
  • a reinterpret_cast (5.2.10), or
  • a reinterpret_cast followed by a const_cast,

can be performed using the cast notation of explicit type conversion. The same semantic restrictions and behaviors apply, with the exception that in performing a static_cast in the following situations the conversion is valid even if the base class is inaccessible:

  • a pointer to an object of derived class type or an lvalue or rvalue of derived class type may be explicitly converted to a pointer or reference to an unambiguous base class type, respectively;
  • [...]

In the situation you've got, the compiler interprets it as a static_cast from Derived* to auto_ptr<Base>, and in that static_cast, a pointer to an object of derived class type is converted to a pointer of an unambiguous base class type. So it looks like the standard allows it.

However, the conversion from Derived* to Base* is implicit, it merely happens to be performed as part of an explicit different conversion. So in the end, no, the standard really doesn't allow it.

You may want to report this as a bug. From Csq's comment, we learn that there is a related report, in which an explicit static_cast also allows this conversion, but it's not exactly the same thing. In that case, the conversion from Derived* to Base* is explicit, but it is implicit here, and Visual C++ does usually reject that in implicit conversions.

Note that in functional casts that use multiple expressions, this misinterpretation isn't possible: the compiler correctly rejects the following:

class Base { };
class Derived : Base { };

template <typename T>
class Ptr {
public:
  Ptr(T *a, T *b) { }
};

int main() {
  Ptr<Base>(new Derived, new Derived);
  // error C2243: 'type cast' : conversion from 'Derived *' to 'Base *' exists, but is inaccessible
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!