...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
An artifact of providing C++ standard library support for quadmath may mandate
the inclusion of <boost/cstdfloat.hpp>
before the inclusion of other headers.
Consider a function that calls fabs(x)
and has previously injected std::fabs()
into local scope via a using
directive:
template <class T> bool unsigned_compare(T a, T b) { using std::fabs; return fabs(a) == fabs(b); }
In this function, the correct overload of fabs
may be found via argument-dependent-lookup
(ADL) or by calling one of the std::fabs
overloads. There is a key difference between them however: an overload in
the same namespace as T and found via ADL need not
be defined at the time the function is declared. However,
all the types declared in <boost/cstdfloat.hpp>
are fundamental types, so for these types we are relying on finding an overload
declared in namespace std
.
In that case however, all such overloads
must be declared prior to the definition of function unsigned_compare
otherwise they are not considered.
In the event that <boost/cstdfloat.hpp>
has been included after the definition of
the above function, the correct overload of fabs
,
while present, is simply not considered as part of the overload set. So the
compiler tries to downcast the float128_t
argument first to long double
,
then to double
, then to float
; the compilation fails because the result
is ambiguous. However the compiler error message will appear cruelly inscrutable,
at an apparently irrelevant line number and making no mention of float128
: the word ambiguous
is the clue to what is wrong.
Provided you #include <boost/cstdfloat.hpp>
before the inclusion of the any header containing
generic floating point code (such as other Boost.Math headers, then the compiler
will know about and use the std::fabs(std::float128_t)
that we provide in #include <boost/cstdfloat.hpp>
.