Skip to content
Snippets Groups Projects
Commit 65ad01ec authored by Jö Fahlke's avatar Jö Fahlke
Browse files

[!550] [DebugAlign] Provide min() and max() overloads.

Merge branch 'debugalign-overload-min-max' into 'master'

A superficial reading of the standard's LessThanComparable requirement may
suggest that we could actually use std::min() and std::max(). But as it turns
out this isn't all that clear, see
<https://cplusplus.github.io/LWG/issue2114>. libc++ chose LessThanComparable
in a way that requires the result of the comparison to be implicitly
convertible to bool, which we cannot guarantee as we do not want the debug
type the automatically decay into its underlying type in all kinds of
contexts. So we go with the alternative route of overloading min() and max().

Adresses: [core/dune-istl#50]

See merge request [core/dune-common!550]

  [core/dune-istl#50]: gitlab.dune-project.org/core/dune-istl/issues/50
  [core/dune-common!550]: gitlab.dune-project.org/core/dune-common/merge_requests/550
parents 709ea8aa 250111a4
No related branches found
No related tags found
No related merge requests found
......@@ -3,6 +3,7 @@
#ifndef DUNE_DEBUGALIGN_HH
#define DUNE_DEBUGALIGN_HH
#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
......@@ -395,6 +396,60 @@ namespace Dune {
#undef DUNE_UNARY_FUNC
// We need to overload min() and max() since they require types to be
// LessThanComparable, which requires `a<b` to be "convertible to bool".
// That wording seems to be a leftover from C++03, and today is probably
// equivalent to "implicitly convertible". There is also issue 2114
// <https://cplusplus.github.io/LWG/issue2114> in the standard (still open
// as of 2018-07-06), which strives to require both "implicitly" and
// "contextually" convertible -- plus a few other things.
//
// We do not want our debug type to automatically decay to the underlying
// type, so we do not want to make the conversion non-explicit. So the
// only option left is to overload min() and max().
template<class T, std::size_t align>
T max(const AlignedNumber<T, align> &a, const AlignedNumber<T, align> &b)
{
using std::max;
return max(T(a), T(b));
}
template<class T, std::size_t align>
T max(const T &a, const AlignedNumber<T, align> &b)
{
using std::max;
return max(a, T(b));
}
template<class T, std::size_t align>
T max(const AlignedNumber<T, align> &a, const T &b)
{
using std::max;
return max(T(a), b);
}
template<class T, std::size_t align>
T min(const AlignedNumber<T, align> &a, const AlignedNumber<T, align> &b)
{
using std::min;
return min(T(a), T(b));
}
template<class T, std::size_t align>
T min(const T &a, const AlignedNumber<T, align> &b)
{
using std::min;
return min(a, T(b));
}
template<class T, std::size_t align>
T min(const AlignedNumber<T, align> &a, const T &b)
{
using std::min;
return min(T(a), b);
}
} // namespace AlignedNumberImpl
// SIMD-like functions from "conditional.hh"
......
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