Skip to content
Snippets Groups Projects
Commit 9c50bb77 authored by Steffen Müthing's avatar Steffen Müthing
Browse files

[referenceelements] Warn users when they capture reference elements by reference

This patch adds partial support for warning users about capturing
reference elements by const ref. Capturing objects with value
semantics by const ref is fine as long as the captured value is not
used outside of the current scope, which can happen e.g. when
assigning to a class member in a constructor. We've had quite a few
problems with this when moving the geometries and entities to value
semantics, so this patch tries to warn as best as it can in this
situation.

It works as long as the user is still explicity using the type
`const Dune::ReferenceElement<ctype,dim>&` for capturing the
reference. Internally, it works by making the type pointed to by the
type alias `Dune::ReferenceElement` a child of the type returned by
the container and providing a deprecated conversion operator to the
derived reference type. The code also makes sure that this still works
in case the value-based reference element returned by the container
has been copied around before by always returning a reference to the
prototype reference element in the container.

This should catch most usages. The user is only out of lucks out if
they already changed to capturing by `auto&`, but in that case,
there's nothing we can do.
parent 887de873
No related branches found
No related tags found
1 merge request!52Rework ReferenceElement interface
#ifndef DUNE_GEOMETRY_REFERENCEELEMENT_HH
#define DUNE_GEOMETRY_REFERENCEELEMENT_HH
#include <dune/common/deprecated.hh>
#include <dune/geometry/type.hh>
namespace Dune {
......@@ -18,6 +20,13 @@ namespace Dune {
template<typename ctype, int dim>
class ReferenceElementImplementation;
// forward declaration for deprecation check reference element type
template<typename ctype, int dim>
class DeprecatedReferenceElement;
// forward declaration for backwards compatibility conversion
template<typename ctype, int dim>
struct ReferenceElements;
// ReferenceElement
// ----------------
......@@ -217,6 +226,16 @@ namespace Dune {
return *_impl;
}
#ifndef DOXYGEN
DUNE_DEPRECATED_MSG("Capturing reference elements by reference is deprecated in DUNE 2.6. Please store a copy instead.")
operator const DeprecatedReferenceElement<ctype,dimension>&() const
{
return ReferenceElements<ctype,dimension>::deprecated(*this);
}
#endif // DOXYGEN
private:
// The implementation must be a friend to construct a wrapper around itself.
......@@ -243,7 +262,7 @@ namespace Dune {
// make type signature of wrapper compatible with old implementation
template<typename ctype, int dim>
using ReferenceElement = Geo::ReferenceElement<Geo::ReferenceElementImplementation<ctype,dim>>;
using ReferenceElement = Geo::DeprecatedReferenceElement<ctype,dim>;
}
......
......@@ -26,6 +26,37 @@ namespace Dune
#ifndef DOXYGEN
template<typename ctype, int dim>
class DeprecatedReferenceElement
: public ReferenceElement<ReferenceElementImplementation<ctype,dim>>
{
protected:
DeprecatedReferenceElement() = default;
public:
DeprecatedReferenceElement(const DeprecatedReferenceElement&) = delete;
DeprecatedReferenceElement& operator=(const DeprecatedReferenceElement&) = delete;
DeprecatedReferenceElement(const ReferenceElementImplementation<ctype,dim>& impl)
: ReferenceElement<ReferenceElementImplementation<ctype,dim>>(impl)
{}
};
template<typename ctype, int dim>
class ConstructibleDeprecatedReferenceElement
: public DeprecatedReferenceElement<ctype,dim>
{
public:
ConstructibleDeprecatedReferenceElement() = default;
};
namespace Impl
{
......@@ -38,9 +69,12 @@ namespace Dune
static const unsigned int numTopologies = (1u << dim);
using Implementation = ReferenceElementImplementation< ctype, dim >;
using ConstructibleDeprecatedReferenceElement = Dune::Geo::ConstructibleDeprecatedReferenceElement<ctype,dim>;
public:
using DeprecatedReferenceElement = Dune::Geo::DeprecatedReferenceElement<ctype,dim>;
using ReferenceElement = Dune::Geo::ReferenceElement< Implementation >;
using value_type = ReferenceElement;
using const_iterator = const value_type*;
......@@ -90,10 +124,19 @@ namespace Dune
return reference_elements_.data() + numTopologies;
}
// here, we make sure to actually return a const reference to something
// that is guaranteed not to become invalid, as otherwise, we might run
// straight into debugging hell when a user binds the return value to a
// const ref and the temporary goes out of scope.
const DeprecatedReferenceElement& deprecated(const ReferenceElement& v) const
{
return reference_elements_[v.impl().type(0,0).id()];
}
private:
std::array<Implementation,numTopologies> implementations_;
std::array<ReferenceElement,numTopologies> reference_elements_;
std::array<ConstructibleDeprecatedReferenceElement,numTopologies> reference_elements_;
};
......@@ -174,6 +217,14 @@ namespace Dune
return container().end();
}
#ifndef DOXYGEN
static const typename Container::DeprecatedReferenceElement&
deprecated(const ReferenceElement& v)
{
return container().deprecated(v);
}
#endif // DOXYGEN
private:
DUNE_EXPORT static const Container& container ()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment