1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
#ifndef DUNE_FUNCTIONS_COMMON_TYPEERASURE_HH
#define DUNE_FUNCTIONS_COMMON_TYPEERASURE_HH
#include <typeinfo>
#include <dune/common/typeutilities.hh>
#include <dune/functions/common/type_traits.hh>
#include <dune/functions/common/interfaces.hh>
#include <dune/functions/common/polymorphicsmallobject.hh>
namespace Dune {
namespace Functions {
namespace Imp {
/**
* \brief The internal wrapper interface for type erasure
*
* \ingroup TypeErasure
*
* This class adds some foundation interfaces needed
* for proper dynamic polymorphism and type erasure.
*
* The actual application interface has to be provided
* by the user.
*
* \tparam Interface Class defininig the internal abstract virtual interface
*/
template<class Interface>
class TypeErasureWrapperInterface :
public Interface,
public PolymorphicType<TypeErasureWrapperInterface<Interface>>
{
public:
virtual const std::type_info& target_type() const = 0;
};
/**
* \brief Base implementation of the internal wrapper interface
*
* \ingroup TypeErasure
*
* This class derives from the foundation interfaces
* and the user defined interfaces provided by the interface
* parameter. It will store any suitable type T to do
* the type erasure.
*
* The implementation of the foundation and user interface
* is provided by classed derived of this one.
*
* \tparam Interface Class defininig the internal abstract virtual interface
* \tparam T A type modelleding the desired interface
*/
template<class Interface, class T>
class TypeErasureWrapperBase :
public TypeErasureWrapperInterface<Interface>
{
public:
template<class TT, disableCopyMove<TypeErasureWrapperBase, TT> = 0>
TypeErasureWrapperBase(TT&& t) :
wrapped_(std::forward<TT>(t))
{}
//! Get mutable reference stored object
T& get()
{
return wrapped_;
}
//! Get reference stored object
const T& get() const
{
return wrapped_;
}
protected:
using Wrapped = T;
Wrapped wrapped_;
};
/**
* \brief Implementation of the internal wrapper interface
*
* \ingroup TypeErasure
*
* This class implements the foundation and user interfaces
* of the internal type erasure wrapper.
*
* The foundation interface of TypeErasureWrapperInterface is directly
* implemented here whereas the user interface is implemented
* by deriving from the user-provides Implementation template.
*
* The Implementation is a template taking one class template
* parameter. It should directly or indirectly derive from this
* class and inherit its constructors.
* In order to forward the implemented methods to the erased
* type it can use the wrapper_ member of this base class being
* of this type.
*
* \tparam Interface Class defining the internal abstract virtual interface
* \tparam Implementation Class defining the implementation of the abstract methods of Interface
* \tparam T A type modeling the desired interface
*/
template<class Interface, template<class> class Implementation, class T>
class TypeErasureWrapperImplementation :
public Implementation<TypeErasureWrapperBase<Interface, T> >
{
public:
//! Construct wrapper from object
template<class TT, disableCopyMove<TypeErasureWrapperImplementation, T> = 0>
TypeErasureWrapperImplementation(TT&& t) :
Implementation<TypeErasureWrapperBase<Interface, T> >(std::forward<TT>(t))
{}
//! Implementation of PolymorphicType::clone()
virtual TypeErasureWrapperImplementation* clone() const
{
return new TypeErasureWrapperImplementation(*this);
}
//! Implementation of PolymorphicType::clone(void* buffer)
virtual TypeErasureWrapperImplementation* clone(void* buffer) const
{
return new (buffer) TypeErasureWrapperImplementation(*this);
}
//! Implementation of PolymorphicType::move(void* buffer)
virtual TypeErasureWrapperImplementation* move(void* buffer)
{
return new (buffer) TypeErasureWrapperImplementation(std::move(*this));
}
//! Get type of stored object
virtual const std::type_info& target_type() const
{
return typeid(T);
}
};
} // namespace Dune::Functions::Imp
/**
* \brief Base class for type-erased interface wrapper
*
* \ingroup TypeErasure
*
* This is meant as a base class for the type-erased interface
* wrapper that is actually visible to the user. By deriving
* from this you get small object optimization for the internal
* polymorphic wrapper.
*/
template<class Interface, template<class> class Implementation, size_t bufferSize = 56>
class TypeErasureBase
{
public:
//! Construct wrapper from object
template<class T, disableCopyMove<TypeErasureBase, T> = 0 >
TypeErasureBase(T&& t) :
wrapped_(Imp::TypeErasureWrapperImplementation<Interface, Implementation, std::decay_t<T>>(std::forward<T>(t)))
{}
//! Default constructor
TypeErasureBase() = default;
//! Get mutable reference to wrapped object
Interface& asInterface()
{
return wrapped_.get();
}
//! Get reference to wrapped object
const Interface& asInterface() const
{
return wrapped_.get();
}
//! Get type of stored object
const std::type_info& target_type() const
{
return wrapped_.get().target_type();
}
protected:
PolymorphicSmallObject<Imp::TypeErasureWrapperInterface<Interface>, bufferSize > wrapped_;
};
}} // namespace Dune::Functions
#endif // DUNE_FUNCTIONS_COMMON_TYPEERASURE_HH
|