Technically speaking there are many more opportunities to mark things as
C++14 constexpr, such as various operators, but doing so would make them
impossible to optimize with various (SIMD) intrisnics unless basically
providing two separate implementations for them, one scalar, slow and
constexpr and the other fast but not compile time, and dispatching with
std::is_constant_evaluated() or some such from C++20.
In other words, such functions cannot and will not be marked as
constexpr in C++17 or older anyway, because the preference is and still
should be runtime perf rather than doing excessive work at compile time,
where it's hard to debug or reasonably test etc etc., and the more you
rebuild the more you'll hate the cost of extra compile time caused by
that.
Co-authored-by: Stanislaw Halik <sthalik@misaki.pl>
Similarly as done in Aug 2024 in Corrade. When these were a part of the
function signature, they ended up being encoded into the exported
symbol. There are still cases of StridedArrayView slice() having
enable_if in the signature, which amounts to about 18 kB symbols in all
libMagnum*-d.so libraries, but apart from that this is the state before:
$ strings libMagnum*-d.so | grep enable_if | grep -v slice | wc -c
29591
And this is after. All of those are coming from STL, thus from
old or deprecated APIs that still use std::vector, std::tuple and such,
and from the few std::sort() uses.
$ strings libMagnum*-d.so | grep enable_if | grep -v slice | wc -c
4103
In a non-deprecated build it's just this, which is a 10x reduction.
Can't really do much about these maybe exceút for implementing my own
swap() specializations (sigh?), but I think it's fine.
$ strings libMagnum*-d.so | grep enable_if | grep -v slice | wc -c
2904
I also made it consistently use
typename std::enable_if<..., int>::type = 0
instead of
class = typename std::enable_if<...>::type
because the former works correctly also in presence of overloads and
having it used consistently everywhere makes it easier to grep & change
later. All SFINAE is now also excluded from Doxygen output, because it
doesn't make much sense there. It's better to just explain the
restriction in words than with this nasty hack.
I did this back in 2010 because it "felt like the right thing to do",
given that all of Magnum depended on Math and not vice versa. But,
strictly speaking, Math already uses typedefs from Magnum/Types.h so why
it couldn't also bring in the Corrade namespace, and the
Debug/Warning/Error names too. Having to type out Corrade:: in all these
was really just a waste of time, weird inconsistency in docs and an
extra roadblock for whoever might want to contribute anything there.
The perf cost is just too great for these to be enabled always. The only
place where the assertions are kept always is in the batch APIs -- there
it's assumed the function is called on large enough data to offset this
overhead, plus since it's often dealing with large blocks of data the
memory safety is more important than various FP drifts which were the
usual case why other assertions were firing.
This makes it possible to conveniently do things like
Containers::StridedArrayView1D<Float> array = …;
Vector4 vector{NoInit};
Utility::copy(array, vector); // or the other way around
which is especially useful together with the new JSON classes. In some
cases this means the function is no longer constexpr, but those weren't
constexpr because it was useful for anything, they were only because it
was possible. So this breakage shouldn't do any harm I think.
The old one is deprecated, and will be removed in a future release.
Unfortunately, to avoid deprecation warnings, all use of NoInit in the
Math library temporarily have to be Magnum::NoInit This will be cleaned
up when the deprecated alias is removed.