diff --git a/dumux/common/optional.hh b/dumux/common/optional.hh new file mode 100644 index 0000000000000000000000000000000000000000..0207724e75605e29627bc682f57d96c903f02c8a --- /dev/null +++ b/dumux/common/optional.hh @@ -0,0 +1,154 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief A wrapper that can either contain an object of T or be empty. + * This might be used as a workaround for non-default constructible classes. + * \note This was adopted from dune-functions. + */ +#ifndef DUMUX_COMMON_OPTIONAL_HH +#define DUMUX_COMMON_OPTIONAL_HH + +#include <utility> + +#include <dune/common/typeutilities.hh> + +namespace Dumux { + +/** + * \brief A wrapper that can either contain an object of T or be empty + * + * \ingroup Utility + * + * \tparam T Type of wrapped objects + */ +template<class T> +class Optional +{ +public: + + Optional() : + p_(nullptr) + {} + + template<class TT, Dune::disableCopyMove<Optional, TT> = 0> + Optional(TT&& t) : + p_(nullptr) + { + emplace(std::forward<TT>(t)); + } + + Optional(Optional&& other) + { + if (other) + p_ = new (buffer_) T(std::move(other.value())); + else + p_ = nullptr; + } + + Optional(const Optional& other) + { + if (other) + p_ = new (buffer_) T(other.value()); + else + p_ = nullptr; + } + + ~Optional() + { + if (operator bool()) + p_->~T(); + } + + template<class TT, Dune::disableCopyMove<Optional, TT> = 0 > + Optional& operator=(TT&& t) + { + if (operator bool()) + *p_ = std::forward<T>(t); + else + p_ = new (buffer_) T(std::forward<T>(t)); + return *this; + } + + Optional& operator=(const Optional& other) + { + if (other) + *this = other.value(); + else if (operator bool()) + { + p_->~T(); + p_ = nullptr; + } + return *this; + } + + Optional& operator=(Optional&& other) + { + if (other) + *this = std::move(other.value()); + else if (operator bool()) + { + p_->~T(); + p_ = nullptr; + } + return *this; + } + + explicit operator bool() const + { + return p_; + } + + const T& value() const + { + return *p_; + } + + T& value() + { + return *p_; + } + + template< class... Args > + void emplace(Args&&... args) + { + if (operator bool()) + p_->~T(); + p_ = new (buffer_) T(std::forward<Args>(args)...); + } + + void release() + { + if (operator bool()) + { + p_->~T(); + p_ = nullptr; + } + } + +private: + + alignas(T) char buffer_[sizeof(T)]; + T* p_; +}; + + +} // namespace Dumux + +#endif // DUMUX_COMMON_OPTIONAL_HH diff --git a/dumux/discretization/cellcentered/tpfa/subcontrolvolume.hh b/dumux/discretization/cellcentered/tpfa/subcontrolvolume.hh index 40d78cfaee6a1fba9e7b0d3d9d338bfbdc28fc19..215915e853786fbedcf8496990f4690b6e0cec6a 100644 --- a/dumux/discretization/cellcentered/tpfa/subcontrolvolume.hh +++ b/dumux/discretization/cellcentered/tpfa/subcontrolvolume.hh @@ -42,6 +42,9 @@ private: using GlobalPosition = Dune::FieldVector<Scalar, dimworld>; public: + // the default constructor + CCTpfaSubControlVolume() = default; + // the contructor in the cc case CCTpfaSubControlVolume(Geometry&& geometry, IndexType elementIndex) diff --git a/dumux/discretization/subcontrolvolumebase.hh b/dumux/discretization/subcontrolvolumebase.hh index 15722ac3e3912547cad7071f3fe1f84b7c80740e..eab6a7a61c2868bf9304e46a3b61c559649c8a82 100644 --- a/dumux/discretization/subcontrolvolumebase.hh +++ b/dumux/discretization/subcontrolvolumebase.hh @@ -24,6 +24,7 @@ #define DUMUX_SUBCONTROLVOLUME_HH #include <dune/common/fvector.hh> +#include <dumux/common/optional.hh> namespace Dumux { @@ -63,6 +64,9 @@ public: elementIndex_(elementIndex) {} + //! Default constructor + SubControlVolumeBase() = default; + //! The copy constrcutor SubControlVolumeBase(const SubControlVolumeBase& other) = delete; @@ -75,11 +79,11 @@ public: //! The move assignment operator SubControlVolumeBase& operator=(SubControlVolumeBase&& other) { - // We want to use the default copy/move assignment operators. - // But since geometry is not assignable :( we - // have to dirty reconstruct it - geometry_.~Geometry(); - new(&geometry_) Geometry(std::move(other.geometry_)); + // We want to use the default copy/move assignment. + // But since geometry is not copy assignable :( we + // have to construct it again + geometry_.release(); + geometry_.emplace(other.geometry_.value()); elementIndex_ = std::move(other.elementIndex_); return *this; } @@ -100,7 +104,7 @@ public: // e.g. for integration const Geometry& geometry() const { - return geometry_; + return geometry_.value(); } //! The global index of the element this scv is embedded in @@ -110,7 +114,8 @@ public: } private: - Geometry geometry_; + // Work around the fact that geometry is not default constructible + Optional<Geometry> geometry_; IndexType elementIndex_; };