It was implemented only for the Half type and not the others, and I just
felt like using it on a vector now, 12 years after the Vector class got
first added.
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.
These shouldn't be needed (the newer classes such as Half or
CubicHermite don't have them and work fine), moreover Clang 12 is now
emitting the following warning for them:
Definition of implicit copy assignment operator for 'Foo' is
deprecated because it has a user-declared copy constructor
[-Wdeprecated-copy]
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.
Now works both ways. The base class works with virtually any combination
that is supported by the underlying types, so e.g. Dual<Matrix3<T>>
could be multiplied/divided with Vector3<T> (result is Vector3<T>), with
Matrix3<T> (result is Matrix3<T>) or with T (result is Matrix3<T>).
The macros, on the other hand, because they are there only to help with
implementation of *my* subclasses, restrict that to the two only cases I
need (i.e. multiplication with Dual<T> and Dual<T::Type> and nothing
else). Could be extended in the future if it needs to be.
Useful for squeezing out last bits of performance, e.g. in this case:
Vector3 a;
a[0] = something++;
a[1] = something++;
a[2] = something++;
In the code all elements are first zeroed out and then overwritten
later, thus it might be good to avoid the zero-initialization:
Vector3 a{Math::NoInit};
a[0] = something++;
a[1] = something++;
a[2] = something++;
This will of course be more useful in far larger data types and arrays
of these.
The only places where they aren't absolute are:
- when header is included from corresponding source file
- when including headers which are not part of final installation (e.g.
test-specific configuration, headers from Implementation/)