diff --git a/doc/conversion.qbk b/doc/conversion.qbk
index bbcd3d0..8cc2344 100644
--- a/doc/conversion.qbk
+++ b/doc/conversion.qbk
@@ -1,5 +1,7 @@
[/
Copyright 2016 Mikhail Maximov.
+ Copyright 2020 Antony Polukhin.
+
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]
@@ -8,15 +10,15 @@
[quickbook 1.6]
[compatibility-mode 1.5]
[id conversion]
- [version 1.6]
+ [version 1.7]
[authors [Stroustrup, Bjarne], [Abrahams, Dave], [Rasin, Boris], [Polukhin, Antony]]
- [copyright 2001 Beman Dawes, 2014-2019 Antony Polukhin]
+ [copyright 2001 Beman Dawes, 2014-2020 Antony Polukhin]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
]
- [source-mode teletype]
+ [source-mode c++]
]
[/ QuickBook Document version 1.5 ]
@@ -44,7 +46,7 @@ the Boost Conversion Library is supplied by several headers:
provides [@boost:libs/lexical_cast/doc/html/index.html `lexical_cast<>`] general literal text conversions, such as an `int` represented as a `string`, or vice-versa.
[endsect]
-
+
[section Polymorphic casts]
Pointers to polymorphic objects (objects of classes which define at
least one virtual function) are sometimes downcast or crosscast.
@@ -58,6 +60,7 @@ safety, suffer poor readability, and are difficult to locate with search
tools.
[#polymorphic_downcast]
+[section polymorphic_downcast]
The C++ built-in `static_cast` can be used for efficiently
downcasting pointers to polymorphic objects, but provides no error
@@ -68,11 +71,11 @@ debug compilations adds safety via an `assert()` that a `dynamic_cast`
succeeds.
A `polymorphic_downcast` should be used for
-downcasts that you are certain should succeed. Error checking is
+downcasts that you are certain should succeed. Error checking is
only performed in translation units where `NDEBUG` is
not defined, via
```
- assert( dynamic_cast(x) == x )
+ assert( dynamic_cast(x) == x )
```
where `x` is the source pointer. This approach
ensures that not only is a non-zero pointer returned, but also
@@ -81,10 +84,26 @@ Attempts to crosscast using `polymorphic_downcast` will
fail to compile.
[warning Because `polymorphic_downcast` uses `assert()`, it
-violates the One Definition Rule (ODR) if NDEBUG is inconsistently
+violates the One Definition Rule (ODR) if `NDEBUG` is inconsistently
defined across translation units. See ISO Std 3.2]
+[h4 Example:]
+```
+ #include
+ ...
+ class Fruit { public: virtual ~Fruit(){}; ... };
+ class Banana : public Fruit { ... };
+ ...
+ void f( Fruit * fruit ) {
+ // ... logic which leads us to believe it is a Banana
+ Banana * banana = boost::polymorphic_downcast(fruit);
+ ...
+ }
+```
+[endsect]
+
[#polymorphic_cast]
+[section polymorphic_cast]
The C++ built-in `dynamic_cast` can be used for downcasts and
crosscasts of pointers to polymorphic objects, but error notification in
@@ -102,88 +121,88 @@ or when efficiency is not important, `polymorphic_cast` is preferred.
The C++ built-in `dynamic_cast` must be used to cast references rather than pointers.
It is also the only cast that can be used to check whether a given interface is supported; in that case a return of 0 isn't an error condition.
+[endsect]
+
+
[#polymorphic_pointer_cast]
+[section polymorphic_pointer_cast]
While `polymorphic_downcast` and `polymorphic_cast` work with built-in pointer types only,
`polymorphic_pointer_downcast` and `polymorphic_pointer_cast` are more generic versions
with support for any pointer type for which the following expressions would be valid:
For `polymorphic_pointer_downcast`:
```
- static_pointer_cast(p);
- dynamic_pointer_cast(p);
+ static_pointer_cast(p);
+ dynamic_pointer_cast(p);
```
For `polymorphic_pointer_cast`:
```
- dynamic_pointer_cast(p);
- !p; // conversion to bool with negation
+ dynamic_pointer_cast(p);
+ !p; // conversion to bool with negation
```
This includes C++ built-in pointers, `std::shared_ptr`,
`boost::shared_ptr`, `boost::intrusive_ptr`, etc.
-[endsect]
-[section `polymorphic_cast`, `polymorphic_downcast`, `polymorphic_pointer_cast` and `polymorphic_pointer_downcast` synopsis]
+
+[h4 Example:]
```
- namespace boost {
+ #include
- template
- inline Derived polymorphic_cast(Base* x);
- // Throws: std::bad_cast if ( dynamic_cast(x) == 0 )
- // Returns: dynamic_cast(x)
+ class Fruit { public: virtual ~Fruit(){} };
+ class Banana : public Fruit {};
- template
- inline Derived polymorphic_downcast(Base* x);
- // Effects: assert( dynamic_cast(x) == x );
- // Returns: static_cast(x)
+ // Use one of these:
+ typedef Fruit* FruitPtr;
+ typedef std::shared_ptr FruitPtr;
+ typedef boost::shared_ptr FruitPtr;
+ typedef boost::intrusive_ptr FruitPtr;
- template
- inline auto polymorphic_pointer_cast(Base x);
- // Throws: std::bad_cast if ( dynamic_pointer_cast(x) == 0 )
- // Returns: dynamic_pointer_cast(x)
+ void f(FruitPtr fruit) {
+ // ... logic which leads us to believe it is a banana
+ auto banana = boost::polymorphic_pointer_downcast(fruit);
+ ...
+ }
+```
- template
- inline auto polymorphic_pointer_downcast(Base x);
- // Effects: assert( dynamic_pointer_cast(x) == x );
- // Returns: static_pointer_cast(x)
+[endsect]
- }
+[endsect]
+
+[section Synopsis]
+```
+ namespace boost {
+
+ // Throws: std::bad_cast if ( dynamic_cast(x) == 0 )
+ // Returns: dynamic_cast(x)
+ template
+ inline Derived polymorphic_cast(Base* x);
+
+ // Effects: assert( dynamic_cast(x) == x );
+ // Returns: static_cast(x)
+ template
+ inline Derived polymorphic_downcast(Base* x);
+
+ // Effects: assert( dynamic_cast(&x) == &x );
+ // Returns: static_cast(x)
+ template
+ inline Derived polymorphic_downcast(Base& x);
+
+ // Throws: std::bad_cast if ( dynamic_pointer_cast(x) == 0 )
+ // Returns: dynamic_pointer_cast(x)
+ template
+ inline auto polymorphic_pointer_cast(Base x);
+
+ // Effects: assert( dynamic_pointer_cast(x) == x );
+ // Returns: static_pointer_cast(x)
+ template
+ inline auto polymorphic_pointer_downcast(Base x);
+
+ }
```
[endsect]
-[section `polymorphic_downcast` example]
-```
- #include
- ...
- class Fruit { public: virtual ~Fruit(){}; ... };
- class Banana : public Fruit { ... };
- ...
- void f( Fruit * fruit ) {
- // ... logic which leads us to believe it is a Banana
- Banana * banana = boost::polymorphic_downcast(fruit);
- ...
- }
-```
-[endsect]
-[section `polymorphic_pointer_downcast` example]
-```
- #include
- class Fruit { public: virtual ~Fruit(){} };
- class Banana : public Fruit {};
- // use one of these:
-
- typedef Fruit* FruitPtr;
- typedef std::shared_ptr FruitPtr;
- typedef boost::shared_ptr FruitPtr;
- typedef boost::intrusive_ptr FruitPtr;
-
- void f(FruitPtr fruit) {
- // ... logic which leads us to believe it is a banana
- auto banana = boost::polymorphic_pointer_downcast(fruit);
- ...
- }
-```
-[endsect]
[section History]
`polymorphic_cast` was suggested by Bjarne Stroustrup in "The C++ Programming Language".
@@ -192,6 +211,8 @@ This includes C++ built-in pointers, `std::shared_ptr`,
`polymorphic_pointer_downcast` was contributed by [@http://www.boost.org/people/boris_rasin.htm Boris Rasin]
and `polymorphic_pointer_cast` by Antony Polukhin.
+`polymorphic_downcast` overload for references was contributed by Julien Delacroix.
+
An old `numeric_cast` that was contributed by [@http://www.boost.org/people/kevlin_henney.htm Kevlin Henney]
-is now superseeded by the [@boost:numeric_conversion/doc/html/html/boost_numericconversion/improved_numeric_cast__.html Boost Numeric Conversion Library]
+is now superseded by the [@boost:numeric_conversion/doc/html/html/boost_numericconversion/improved_numeric_cast__.html Boost Numeric Conversion Library]
[endsect]
diff --git a/include/boost/implicit_cast.hpp b/include/boost/implicit_cast.hpp
index d82db76..03abe1d 100644
--- a/include/boost/implicit_cast.hpp
+++ b/include/boost/implicit_cast.hpp
@@ -2,8 +2,9 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef IMPLICIT_CAST_DWA200356_HPP
-# define IMPLICIT_CAST_DWA200356_HPP
+
+#ifndef BOOST_IMPLICIT_CAST_DWA200356_HPP
+#define BOOST_IMPLICIT_CAST_DWA200356_HPP
namespace boost {
@@ -26,11 +27,7 @@ inline T implicit_cast (typename boost::detail::icast_identity::type x) {
return x;
}
-// incomplete return type now is here
-//template
-//void implicit_cast (...);
-
} // namespace boost
-#endif // IMPLICIT_CAST_DWA200356_HPP
+#endif // BOOST_IMPLICIT_CAST_DWA200356_HPP
diff --git a/include/boost/polymorphic_cast.hpp b/include/boost/polymorphic_cast.hpp
index 802ac9a..3592506 100644
--- a/include/boost/polymorphic_cast.hpp
+++ b/include/boost/polymorphic_cast.hpp
@@ -50,17 +50,20 @@
#define BOOST_POLYMORPHIC_CAST_HPP
# include
-# include
-# include
-# include
-# include
-# include
-# include
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
+# include
+# include
+# include
+# include
+# include
+# include
+
+# include
+
namespace boost
{
// See the documentation for descriptions of how to choose between
@@ -108,10 +111,14 @@ namespace boost
// Contributed by Julien Delacroix
template
- inline typename boost::enable_if_c::value, Target>::type polymorphic_downcast(Source &x)
+ inline typename boost::enable_if_c<
+ boost::is_reference::value, Target
+ >::type polymorphic_downcast(Source& x)
{
- BOOST_ASSERT(dynamic_cast::type *>(&x) == &x);
- return static_cast(x);
+ typedef typename boost::remove_reference::type* target_pointer_type;
+ return *boost::polymorphic_downcast(
+ boost::addressof(x)
+ );
}
} // namespace boost