-New: There is now a function dynamic_unique_cast() that does for
-`std::unique_ptr` objects what `dynamic_cast` does for regular
-pointers.
+New: There is now a function Utilities::dynamic_unique_cast() that does for
+`std::unique_ptr` objects what `dynamic_cast` does for regular pointers.
<br>
(Wolfgang Bangerth, 2018/04/03)
namespace std_cxx1x = std_cxx11;
DEAL_II_NAMESPACE_CLOSE
-
-DEAL_II_NAMESPACE_OPEN
-
-/**
- * Convert an object of type `std::unique_ptr<From>` to an object of
- * type `std::unique_ptr<To>`, where it is assumed that we can cast
- * the pointer to `From` to a pointer to `To` using a `dynamic_cast`
- * -- in other words, we assume that `From` and `To` are connected
- * through a class hierarchy, and that the object pointed to is in
- * fact of a type that contains both a `From` and a `To`. An example
- * is if either `To` is derived from `From` or the other way around.
- *
- * The function throws an exception of type `std::bad_cast` if the
- * `dynamic_cast` does not succeed. This is the same exception you
- * would get if a regular `dynamic_cast` between object types (but not
- * pointer types) does not succeed.
- *
- * An example of how this function works is as follows:
- * @code
- * class B { ... }; // A base class. Assume that it has virtual
- * // functions so that dynamic_cast can work.
- * class D : public B { ... }; // A derived class
- *
- *
- * std::unique_ptr<B> create_object (...) {...} // A factory function
- *
- * void foo (...)
- * {
- * std::unique_ptr<B> b = create_object (...);
- *
- * // Assume that we know for some reason that the object above must
- * // have created a D object but returned it as a std::unique_ptr<B>.
- * // In order to access the D functionality, we need to cast the
- * // pointer. Use the equivalent to dynamic_cast:
- * std::unique_ptr<D> d = dynamic_unique_cast<D>(std::move(b));
- *
- * // If the object really was a D, then 'd' now points to it. Note
- * // also that in accordance with the semantics of std::unique_ptr,
- * // it was necessary to std::move the 'b' object, and indeed 'b'
- * // now no longer points to anything -- ownership has been
- * // transferred to 'd'!
- * @endcode
- *
- * @note This function does not try to convert the `Deleter` objects stored
- * by `std::unique_ptr` objects. The function therefore only works if the
- * deleter objects are at their defaults, i.e., if they are of type
- * `std::default_delete<To>` and `std::default_delete<From>`.
- */
-template <typename To, typename From>
-std::unique_ptr<To>
-dynamic_unique_cast (std::unique_ptr<From> &&p)
-{
- // Let's see if we can cast from 'From' to 'To'. If so, do the cast,
- // and then release the pointer from the old
- // owner
- if (To *cast = dynamic_cast<To *>(p.get()))
- {
- std::unique_ptr<To> result(cast);
- p.release();
- return result;
- }
- else
- throw std::bad_cast();
-}
-
-DEAL_II_NAMESPACE_CLOSE
-
#endif
void unpack (const std::vector<char> &buffer,
T (&unpacked_object)[N]);
+ /**
+ * Convert an object of type `std::unique_ptr<From>` to an object of
+ * type `std::unique_ptr<To>`, where it is assumed that we can cast
+ * the pointer to `From` to a pointer to `To` using a `dynamic_cast`
+ * -- in other words, we assume that `From` and `To` are connected
+ * through a class hierarchy, and that the object pointed to is in
+ * fact of a type that contains both a `From` and a `To`. An example
+ * is if either `To` is derived from `From` or the other way around.
+ *
+ * The function throws an exception of type `std::bad_cast` if the
+ * `dynamic_cast` does not succeed. This is the same exception you
+ * would get if a regular `dynamic_cast` between object types (but not
+ * pointer types) does not succeed.
+ *
+ * An example of how this function works is as follows:
+ * @code
+ * class B { ... }; // A base class. Assume that it has virtual
+ * // functions so that dynamic_cast can work.
+ * class D : public B { ... }; // A derived class
+ *
+ *
+ * std::unique_ptr<B> create_object (...) {...} // A factory function
+ *
+ * void foo (...)
+ * {
+ * std::unique_ptr<B> b = create_object (...);
+ *
+ * // Assume that we know for some reason that the object above must
+ * // have created a D object but returned it as a std::unique_ptr<B>.
+ * // In order to access the D functionality, we need to cast the
+ * // pointer. Use the equivalent to dynamic_cast:
+ * std::unique_ptr<D> d = dynamic_unique_cast<D>(std::move(b));
+ *
+ * // If the object really was a D, then 'd' now points to it. Note
+ * // also that in accordance with the semantics of std::unique_ptr,
+ * // it was necessary to std::move the 'b' object, and indeed 'b'
+ * // now no longer points to anything -- ownership has been
+ * // transferred to 'd'!
+ * @endcode
+ *
+ * @note This function does not try to convert the `Deleter` objects stored
+ * by `std::unique_ptr` objects. The function therefore only works if the
+ * deleter objects are at their defaults, i.e., if they are of type
+ * `std::default_delete<To>` and `std::default_delete<From>`.
+ */
+ template <typename To, typename From>
+ std::unique_ptr<To>
+ dynamic_unique_cast (std::unique_ptr<From> &&p)
+ {
+ // Let's see if we can cast from 'From' to 'To'. If so, do the cast,
+ // and then release the pointer from the old
+ // owner
+ if (To *cast = dynamic_cast<To *>(p.get()))
+ {
+ std::unique_ptr<To> result(cast);
+ p.release();
+ return result;
+ }
+ else
+ throw std::bad_cast();
+ }
+
/**
* A namespace for utility functions that probe system properties.
*
//
// ---------------------------------------------------------------------
-#include <deal.II/base/std_cxx11/unique_ptr.h>
#include <deal.II/base/array_view.h>
#include <deal.II/base/polynomial.h>
#include <deal.II/base/quadrature.h>
quadrature);
if (!use_mapping_q_on_all_cells)
- data->mapping_q1_data = dynamic_unique_cast<typename MappingQGeneric<dim,spacedim>::InternalData>
+ data->mapping_q1_data = Utilities::dynamic_unique_cast<typename MappingQGeneric<dim,spacedim>::InternalData>
(std::move(q1_mapping->get_data (update_flags, quadrature)));
// wait for the task above to finish and use returned value
- data->mapping_qp_data = dynamic_unique_cast<typename MappingQGeneric<dim,spacedim>::InternalData>
+ data->mapping_qp_data = Utilities::dynamic_unique_cast<typename MappingQGeneric<dim,spacedim>::InternalData>
(std::move(do_get_data.return_value()));
return std::move(data);
quadrature);
if (!use_mapping_q_on_all_cells)
- data->mapping_q1_data = dynamic_unique_cast<typename MappingQGeneric<dim,spacedim>::InternalData>
+ data->mapping_q1_data = Utilities::dynamic_unique_cast<typename MappingQGeneric<dim,spacedim>::InternalData>
(std::move(q1_mapping->get_face_data (update_flags, quadrature)));
// wait for the task above to finish and use returned value
- data->mapping_qp_data = dynamic_unique_cast<typename MappingQGeneric<dim,spacedim>::InternalData>
+ data->mapping_qp_data = Utilities::dynamic_unique_cast<typename MappingQGeneric<dim,spacedim>::InternalData>
(std::move(do_get_data.return_value()));
return std::move(data);
}
quadrature);
if (!use_mapping_q_on_all_cells)
- data->mapping_q1_data = dynamic_unique_cast<typename MappingQGeneric<dim,spacedim>::InternalData>
+ data->mapping_q1_data = Utilities::dynamic_unique_cast<typename MappingQGeneric<dim,spacedim>::InternalData>
(std::move(q1_mapping->get_subface_data (update_flags, quadrature)));
// wait for the task above to finish and use returned value
- data->mapping_qp_data = dynamic_unique_cast<typename MappingQGeneric<dim,spacedim>::InternalData>
+ data->mapping_qp_data = Utilities::dynamic_unique_cast<typename MappingQGeneric<dim,spacedim>::InternalData>
(std::move(do_get_data.return_value()));
return std::move(data);
}
#include "../tests.h"
-#include <deal.II/base/std_cxx11/unique_ptr.h>
-
-
class B
{
public:
std::unique_ptr<D> d = std_cxx14::make_unique<D>();
// See that we can successfully downcast to B
- std::unique_ptr<B> b = dynamic_unique_cast<B>(std::move(d));
+ std::unique_ptr<B> b = Utilities::dynamic_unique_cast<B>(std::move(d));
// Ownership now rests with b, but it's still a D. Verify this:
Assert (d.get() == nullptr, ExcInternalError());
Assert (dynamic_cast<D *>(b.get()) != nullptr, ExcInternalError());
// Check that we can again upcast to D:
- std::unique_ptr<D> dd = dynamic_unique_cast<D>(std::move(b));
+ std::unique_ptr<D> dd = Utilities::dynamic_unique_cast<D>(std::move(b));
// Ownership now rests with b, but it's still a D. Verify this:
Assert (b.get() == nullptr, ExcInternalError());
// Check that we can indeed not upcast to D:
try
{
- std::unique_ptr<D> dd = dynamic_unique_cast<D>(std::move(b));
+ std::unique_ptr<D> dd = Utilities::dynamic_unique_cast<D>(std::move(b));
}
catch (const std::bad_cast &)
{