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

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

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: dune-istl#50
parent 9d4e38b7
Branches
Tags
1 merge request!550[DebugAlign] Provide min() and max() overloads.
Pipeline #10537 passed
......@@ -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.
Please register or to comment