Browse Source

Convert all argument / return SFINAE into template argument SFINAE.

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.
pull/674/head
Vladimír Vondruš 1 year ago
parent
commit
02a0960d12
  1. 12
      src/Magnum/AbstractResourceLoader.h
  2. 6
      src/Magnum/Animation/Track.h
  3. 13
      src/Magnum/Array.h
  4. 6
      src/Magnum/GL/Attribute.h
  5. 6
      src/Magnum/GL/Context.h
  6. 14
      src/Magnum/GL/Mesh.h
  7. 10
      src/Magnum/GL/MultisampleTexture.h
  8. 3
      src/Magnum/GL/Shader.h
  9. 12
      src/Magnum/GL/Texture.h
  10. 4
      src/Magnum/GL/TextureArray.h
  11. 4
      src/Magnum/Image.h
  12. 40
      src/Magnum/ImageView.h
  13. 6
      src/Magnum/Math/Bezier.h
  14. 27
      src/Magnum/Math/BitVector.h
  15. 64
      src/Magnum/Math/Color.h
  16. 17
      src/Magnum/Math/CubicHermite.h
  17. 31
      src/Magnum/Math/Dual.h
  18. 116
      src/Magnum/Math/Functions.h
  19. 2
      src/Magnum/Math/FunctionsBatch.h
  20. 10
      src/Magnum/Math/Packing.h
  21. 8
      src/Magnum/Math/Range.h
  22. 4
      src/Magnum/Math/Test/TypeTraitsTest.cpp
  23. 12
      src/Magnum/Math/TypeTraits.h
  24. 73
      src/Magnum/Math/Unit.h
  25. 342
      src/Magnum/Math/Vector.h
  26. 16
      src/Magnum/Math/Vector2.h
  27. 8
      src/Magnum/MeshTools/Interleave.h
  28. 4
      src/Magnum/Platform/ScreenedApplication.h
  29. 2
      src/Magnum/SceneGraph/AbstractFeature.h
  30. 2
      src/Magnum/SceneGraph/Animable.h
  31. 2
      src/Magnum/SceneGraph/Camera.h
  32. 2
      src/Magnum/SceneGraph/Drawable.h
  33. 30
      src/Magnum/Trade/MaterialData.h
  34. 72
      src/Magnum/Trade/MeshData.h
  35. 66
      src/Magnum/Trade/SceneData.h
  36. 12
      src/Magnum/Vk/Extensions.h
  37. 2
      src/Magnum/Vk/Implementation/structureHelpers.h

12
src/Magnum/AbstractResourceLoader.h

@ -152,7 +152,11 @@ template<class T> class AbstractResourceLoader {
}
/** @overload */
template<class U, class = typename std::enable_if<!std::is_same<typename std::decay<U>::type, std::nullptr_t>::value>::type> void set(ResourceKey key, U&& data, ResourceDataState state, ResourcePolicy policy) {
template<class U
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!std::is_same<typename std::decay<U>::type, std::nullptr_t>::value, int>::type = 0
#endif
> void set(ResourceKey key, U&& data, ResourceDataState state, ResourcePolicy policy) {
set(key, new typename std::decay<U>::type(std::forward<U>(data)), state, policy);
}
@ -172,7 +176,11 @@ template<class T> class AbstractResourceLoader {
}
/** @overload */
template<class U, class = typename std::enable_if<!std::is_same<typename std::decay<U>::type, std::nullptr_t>::value>::type> void set(ResourceKey key, U&& data) {
template<class U
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!std::is_same<typename std::decay<U>::type, std::nullptr_t>::value, int>::type = 0
#endif
> void set(ResourceKey key, U&& data) {
set(key, new typename std::decay<U>::type(std::forward<U>(data)));
}

6
src/Magnum/Animation/Track.h

@ -734,7 +734,11 @@ template<class K, class V, class R
/** @brief Convert a mutable view to a const one */
/* This is the only variant that works on MSVC 2015, std::remove_const
in the signature didn't work there */
template<class K2, class V2, class = typename std::enable_if<std::is_same<const K2, K>::value && std::is_same<const V2, V>::value>::type> /*implicit*/ TrackView(const TrackView<K2, V2, R>& other) noexcept: TrackViewStorage<K>{other._keys, other._values, other._interpolation, other._interpolator, other._before, other._after} {}
template<class K2, class V2
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_same<const K2, K>::value && std::is_same<const V2, V>::value, int>::type = 0
#endif
> /*implicit*/ TrackView(const TrackView<K2, V2, R>& other) noexcept: TrackViewStorage<K>{other._keys, other._values, other._interpolation, other._interpolator, other._before, other._after} {}
/**
* @brief Interpolation function

13
src/Magnum/Array.h

@ -82,11 +82,11 @@ template<UnsignedInt dimensions, class T> class CORRADE_DEPRECATED("use Math::Ve
* @param first First value
* @param next Next values
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class ...U> constexpr /*implicit*/ Array(T first, U... next);
#else
template<class ...U, class V = typename std::enable_if<sizeof...(U)+1 == dimensions, T>::type> constexpr /*implicit*/ Array(T first, U... next): _data{first, next...} {}
#endif
template<class ...U
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<sizeof...(U)+1 == dimensions, int>::type = 0
#endif
> constexpr /*implicit*/ Array(T first, U... next): _data{first, next...} {}
/** @brief Construct array with one value for all fields */
#ifdef DOXYGEN_GENERATING_OUTPUT
@ -95,8 +95,7 @@ template<UnsignedInt dimensions, class T> class CORRADE_DEPRECATED("use Math::Ve
#ifdef CORRADE_TARGET_MSVC /* MSVC warns for the constructor delegation */
CORRADE_IGNORE_DEPRECATED_PUSH
#endif
template<class U, class V = typename std::enable_if<std::is_same<T, U>::value && dimensions != 1, T>::type>
constexpr /*implicit*/ Array(U value): Array(typename Containers::Implementation::GenerateSequence<dimensions>::Type{}, value) {}
template<class U, typename std::enable_if<std::is_same<T, U>::value && dimensions != 1, int>::type = 0> constexpr /*implicit*/ Array(U value): Array(typename Containers::Implementation::GenerateSequence<dimensions>::Type{}, value) {}
#ifdef CORRADE_TARGET_MSVC
CORRADE_IGNORE_DEPRECATED_POP
#endif

6
src/Magnum/GL/Attribute.h

@ -786,18 +786,18 @@ MAGNUM_GL_EXPORT bool hasVertexFormat(Magnum::VertexFormat format);
namespace Implementation {
template<UnsignedInt location, class T> constexpr DynamicAttribute::Kind kindFor(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Float>::value, typename GL::Attribute<location, T>::DataOptions>::type options) {
template<UnsignedInt location, class T, typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Float>::value, int>::type = 0> constexpr DynamicAttribute::Kind kindFor(typename GL::Attribute<location, T>::DataOptions options) {
return options & GL::Attribute<location, T>::DataOption::Normalized ?
DynamicAttribute::Kind::GenericNormalized : DynamicAttribute::Kind::Generic;
}
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt location, class T> constexpr DynamicAttribute::Kind kindFor(typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::ScalarType>::value, typename GL::Attribute<location, T>::DataOptions>::type) {
template<UnsignedInt location, class T, typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::ScalarType>::value, int>::type = 0> constexpr DynamicAttribute::Kind kindFor(typename GL::Attribute<location, T>::DataOptions) {
return DynamicAttribute::Kind::Integral;
}
#ifndef MAGNUM_TARGET_GLES
template<UnsignedInt location, class T> constexpr DynamicAttribute::Kind kindFor(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Double>::value, typename GL::Attribute<location, T>::DataOptions>::type) {
template<UnsignedInt location, class T, typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Double>::value, int>::type = 0> constexpr DynamicAttribute::Kind kindFor(typename GL::Attribute<location, T>::DataOptions) {
return DynamicAttribute::Kind::Long;
}
#endif

6
src/Magnum/GL/Context.h

@ -109,7 +109,11 @@ class MAGNUM_GL_EXPORT Extension {
constexpr const char* string() const { return _string; }
/** @brief Construct from a compile-time extension */
template<class E, class = typename std::enable_if<Implementation::IsExtension<E>::value>::type> constexpr /*implicit*/ Extension(const E&): _index{E::Index}, _requiredVersion{E::requiredVersion()}, _coreVersion{E::coreVersion()}, _string{E::string()} {}
template<class E
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<Implementation::IsExtension<E>::value, int>::type = 0
#endif
> constexpr /*implicit*/ Extension(const E&): _index{E::Index}, _requiredVersion{E::requiredVersion()}, _coreVersion{E::coreVersion()}, _string{E::string()} {}
private:
std::size_t _index;

14
src/Magnum/GL/Mesh.h

@ -911,7 +911,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
template<class ...T
#ifndef DOXYGEN_GENERATING_OUTPUT
/* So it doesn't clash with the DynamicAttribute overload */
, class = typename std::enable_if<!Implementation::IsDynamicAttribute<T...>::value>::type
, typename std::enable_if<!Implementation::IsDynamicAttribute<T...>::value, int>::type = 0
#endif
> Mesh& addVertexBuffer(Buffer& buffer, GLintptr offset, const T&... attributes) {
addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), 0, attributes...);
@ -952,7 +952,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
template<class ...T
#ifndef DOXYGEN_GENERATING_OUTPUT
/* So it doesn't clash with the DynamicAttribute overload */
, class = typename std::enable_if<!Implementation::IsDynamicAttribute<T...>::value>::type
, typename std::enable_if<!Implementation::IsDynamicAttribute<T...>::value, int>::type = 0
#endif
> Mesh& addVertexBufferInstanced(Buffer& buffer, UnsignedInt divisor, GLintptr offset, const T&... attributes) {
addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), divisor, attributes...);
@ -996,7 +996,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
template<class ...T
#ifndef DOXYGEN_GENERATING_OUTPUT
/* So it doesn't clash with the DynamicAttribute overload */
, class = typename std::enable_if<!Implementation::IsDynamicAttribute<T...>::value>::type
, typename std::enable_if<!Implementation::IsDynamicAttribute<T...>::value, int>::type = 0
#endif
> Mesh& addVertexBuffer(Buffer&& buffer, GLintptr offset, const T&... attributes) {
addVertexBuffer<T...>(buffer, offset, attributes...);
@ -1015,7 +1015,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
template<class ...T
#ifndef DOXYGEN_GENERATING_OUTPUT
/* So it doesn't clash with the DynamicAttribute overload */
, class = typename std::enable_if<!Implementation::IsDynamicAttribute<T...>::value>::type
, typename std::enable_if<!Implementation::IsDynamicAttribute<T...>::value, int>::type = 0
#endif
> Mesh& addVertexBufferInstanced(Buffer&& buffer, UnsignedInt divisor, GLintptr offset, const T&... attributes) {
addVertexBufferInstanced<T...>(buffer, divisor, offset, attributes...);
@ -1224,7 +1224,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
}
void addVertexBufferInternal(Buffer&, GLintptr, GLsizei, GLuint) {}
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Float>::value, Buffer&>::type buffer, const Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
template<UnsignedInt location, class T, typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Float>::value, int>::type = 0> void addVertexAttribute(Buffer& buffer, const Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
for(UnsignedInt i = 0; i != Attribute<location, T>::Vectors; ++i)
attributePointerInternal(buffer,
location+i,
@ -1237,7 +1237,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
}
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::ScalarType>::value, Buffer&>::type buffer, const Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
template<UnsignedInt location, class T, typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::ScalarType>::value, int>::type = 0> void addVertexAttribute(Buffer& buffer, const Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
attributePointerInternal(buffer,
location,
GLint(attribute.components()),
@ -1249,7 +1249,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
}
#ifndef MAGNUM_TARGET_GLES
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Double>::value, Buffer&>::type buffer, const Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
template<UnsignedInt location, class T, typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Double>::value, int>::type = 0> void addVertexAttribute(Buffer& buffer, const Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
for(UnsignedInt i = 0; i != Attribute<location, T>::Vectors; ++i)
attributePointerInternal(buffer,
location+i,

10
src/Magnum/GL/MultisampleTexture.h

@ -165,7 +165,7 @@ MultisampleTexture: public AbstractTexture {
* @gl_extension{EXT,texture_view}
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 2>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d == 2, int>::type = 0>
#endif
static MultisampleTexture<dimensions> view(MultisampleTexture2DArray& original, TextureFormat internalFormat, Int layer);
@ -186,7 +186,7 @@ MultisampleTexture: public AbstractTexture {
* @gl_extension{EXT,texture_view}
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 3>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d == 3, int>::type = 0>
#endif
static MultisampleTexture<dimensions> view(MultisampleTexture2DArray& original, TextureFormat internalFormat, Int layerOffset, Int layerCount);
@ -252,7 +252,7 @@ MultisampleTexture: public AbstractTexture {
* @requires_gl42 Extension @gl_extension{ARB,shader_image_load_store}
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 2>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d == 2, int>::type = 0>
#endif
void bindImage(Int imageUnit, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, 0, false, 0, access, format);
@ -279,7 +279,7 @@ MultisampleTexture: public AbstractTexture {
* multisample 2D array textures.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 3>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d == 3, int>::type = 0>
#endif
void bindImage(Int imageUnit, Int layer, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, 0, false, layer, access, format);
@ -305,7 +305,7 @@ MultisampleTexture: public AbstractTexture {
* multisample 2D array textures.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 3>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d == 3, int>::type = 0>
#endif
void bindImageLayered(Int imageUnit, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, 0, true, 0, access, format);

3
src/Magnum/GL/Shader.h

@ -716,8 +716,7 @@ class MAGNUM_GL_EXPORT Shader: public AbstractObject {
#else
/* Otherwise passing a char* is ambiguous between this and the
StringView overload. Sigh, C++. */
template<class U, class = typename std::enable_if<std::is_same<U&&, Containers::String&&>::value>::type>
Shader& addSource(U&& source) {
template<class U, typename std::enable_if<std::is_same<U&&, Containers::String&&>::value, int>::type = 0> Shader& addSource(U&& source) {
return addSourceInternal(Utility::move(source));
}
#endif

12
src/Magnum/GL/Texture.h

@ -196,7 +196,7 @@ Texture: public AbstractTexture {
* @requires_gles Texture views are not available in WebGL.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d <= 2>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d <= 2, int>::type = 0>
#endif
static Texture<dimensions> view(TextureArray<dimensions>& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layer);
@ -217,7 +217,7 @@ Texture: public AbstractTexture {
* @requires_gles Texture views are not available in WebGL.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 2>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d == 2, int>::type = 0>
#endif
static Texture<dimensions> view(CubeMapTexture& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layer);
@ -238,7 +238,7 @@ Texture: public AbstractTexture {
* @requires_gles Texture views are not available in WebGL.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 2>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d == 2, int>::type = 0>
#endif
static Texture<dimensions> view(CubeMapTextureArray& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layer);
#endif
@ -320,7 +320,7 @@ Texture: public AbstractTexture {
* @requires_gles Shader image load/store is not available in WebGL.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 1 || d == 2>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d == 1 || d == 2, int>::type = 0>
#endif
void bindImage(Int imageUnit, Int level, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, level, false, 0, access, format);
@ -348,7 +348,7 @@ Texture: public AbstractTexture {
* @requires_gles Shader image load/store is not available in WebGL.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 3>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d == 3, int>::type = 0>
#endif
void bindImage(Int imageUnit, Int level, Int layer, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, level, false, layer, access, format);
@ -375,7 +375,7 @@ Texture: public AbstractTexture {
* @requires_gles Shader image load/store is not available in WebGL.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 3>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d == 3, int>::type = 0>
#endif
void bindImageLayered(Int imageUnit, Int level, ImageAccess access, ImageFormat format) {
bindImageInternal(imageUnit, level, true, 0, access, format);

4
src/Magnum/GL/TextureArray.h

@ -199,7 +199,7 @@ TextureArray: public AbstractTexture {
* @requires_gles Texture views are not available in WebGL.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 2>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d == 2, int>::type = 0>
#endif
static TextureArray<dimensions> view(CubeMapTexture& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layerOffset, Int layerCount);
@ -220,7 +220,7 @@ TextureArray: public AbstractTexture {
* @requires_gles Texture views are not available in WebGL.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 2>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d == 2, int>::type = 0>
#endif
static TextureArray<dimensions> view(CubeMapTextureArray& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layerOffset, Int layerCount);
#endif

4
src/Magnum/Image.h

@ -358,9 +358,9 @@ template<UnsignedInt dimensions> class Image {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
/* Otherwise this catches too much, resulting in weird errors */
, class = typename std::enable_if<std::is_enum<T>::value || std::is_integral<T>::value>::type
, typename std::enable_if<std::is_enum<T>::value || std::is_integral<T>::value, int>::type = 0
#endif
> /*implicit*/ Image(T format) noexcept: Image{{}, format} {}
> /*implicit*/ Image(T format) noexcept: Image{{}, format} {}
/** @brief Copying is not allowed */
Image(const Image<dimensions>&) = delete;

40
src/Magnum/ImageView.h

@ -424,13 +424,21 @@ template<UnsignedInt dimensions, class T> class ImageView {
* there's no concept of 2D arrays of 1D images. Use the @p flags
* parameter to add arbitrary other flags.
*/
template<UnsignedInt otherDimensions, class = typename std::enable_if<(otherDimensions < dimensions)>::type> /*implicit*/ ImageView(const ImageView<otherDimensions, T>& other, ImageFlags<dimensions> flags = {}) noexcept;
template<UnsignedInt otherDimensions
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<(otherDimensions < dimensions), int>::type = 0
#endif
> /*implicit*/ ImageView(const ImageView<otherDimensions, T>& other, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Convert a mutable view to a const one
* @m_since{2019,10}
*/
template<class U, class = typename std::enable_if<std::is_const<T>::value && !std::is_const<U>::value>::type> /*implicit*/ ImageView(const ImageView<dimensions, U>& other) noexcept;
template<class U
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_const<T>::value && !std::is_const<U>::value, int>::type = 0
#endif
> /*implicit*/ ImageView(const ImageView<dimensions, U>& other) noexcept;
/**
* @brief Layout flags
@ -830,13 +838,21 @@ template<UnsignedInt dimensions, class T> class CompressedImageView {
* there's no concept of 2D arrays of 1D images. Use the @p flags
* parameter to add arbitrary other flags.
*/
template<UnsignedInt otherDimensions, class = typename std::enable_if<(otherDimensions < dimensions)>::type> /*implicit*/ CompressedImageView(const CompressedImageView<otherDimensions, T>& other, ImageFlags<dimensions> flags = {}) noexcept;
template<UnsignedInt otherDimensions
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<(otherDimensions < dimensions), int>::type = 0
#endif
> /*implicit*/ CompressedImageView(const CompressedImageView<otherDimensions, T>& other, ImageFlags<dimensions> flags = {}) noexcept;
/**
* @brief Convert a mutable view to a const one
* @m_since{2019,10}
*/
template<class U, class = typename std::enable_if<std::is_const<T>::value && !std::is_const<U>::value>::type> /*implicit*/ CompressedImageView(const CompressedImageView<dimensions, U>& other) noexcept;
template<class U
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_const<T>::value && !std::is_const<U>::value, int>::type = 0
#endif
> /*implicit*/ CompressedImageView(const CompressedImageView<dimensions, U>& other) noexcept;
/**
* @brief Layout flags
@ -994,8 +1010,8 @@ template<UnsignedInt dimensions, class T> template<class U> inline ImageView<dim
"format types larger than 32bits are not supported");
}
#ifndef DOXYGEN_GENERATING_OUTPUT /* it complains otherwise. why? don't know, don't want to know */
template<UnsignedInt dimensions, class T> template<UnsignedInt otherDimensions, class> ImageView<dimensions, T>::ImageView(const ImageView<otherDimensions, T>& other, const ImageFlags<dimensions> flags) noexcept:
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt dimensions, class T> template<UnsignedInt otherDimensions, typename std::enable_if<(otherDimensions < dimensions), int>::type> ImageView<dimensions, T>::ImageView(const ImageView<otherDimensions, T>& other, const ImageFlags<dimensions> flags) noexcept:
_storage{other._storage},
_format{other._format},
_formatExtra{other._formatExtra},
@ -1004,9 +1020,9 @@ template<UnsignedInt dimensions, class T> template<UnsignedInt otherDimensions,
_flags{ImageFlag<dimensions>(UnsignedShort(other._flags)&~UnsignedShort(ImageFlag2D::Array))|flags},
_size{Math::Vector<dimensions, Int>::pad(other._size, 1)},
_data{other._data} {}
#endif
template<UnsignedInt dimensions, class T> template<class U, class> ImageView<dimensions, T>::ImageView(const ImageView<dimensions, U>& other) noexcept: _storage{other._storage}, _format{other._format}, _formatExtra{other._formatExtra}, _pixelSize{other._pixelSize}, _flags{other._flags}, _size{other._size}, _data{other._data} {}
template<UnsignedInt dimensions, class T> template<class U, typename std::enable_if<std::is_const<T>::value && !std::is_const<U>::value, int>::type> ImageView<dimensions, T>::ImageView(const ImageView<dimensions, U>& other) noexcept: _storage{other._storage}, _format{other._format}, _formatExtra{other._formatExtra}, _pixelSize{other._pixelSize}, _flags{other._flags}, _size{other._size}, _data{other._data} {}
#endif
template<UnsignedInt dimensions, class T> template<class U> inline CompressedImageView<dimensions, T>::CompressedImageView(const CompressedPixelStorage storage, const U format, const VectorTypeFor<dimensions, Int>& size, const Containers::ArrayView<ErasedType> data, const ImageFlags<dimensions> flags) noexcept: CompressedImageView{storage, UnsignedInt(format), size, data, flags} {
static_assert(sizeof(U) <= 4,
@ -1018,17 +1034,17 @@ template<UnsignedInt dimensions, class T> template<class U> inline CompressedIma
"format types larger than 32bits are not supported");
}
#ifndef DOXYGEN_GENERATING_OUTPUT /* it complains otherwise. why? don't know, don't want to know */
template<UnsignedInt dimensions, class T> template<UnsignedInt otherDimensions, class> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedImageView<otherDimensions, T>& other, const ImageFlags<dimensions> flags) noexcept:
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt dimensions, class T> template<UnsignedInt otherDimensions, typename std::enable_if<(otherDimensions < dimensions), int>::type> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedImageView<otherDimensions, T>& other, const ImageFlags<dimensions> flags) noexcept:
_storage{other._storage},
_format{other._format},
/* Removing the Array bit and transferring the rest, as documented */
_flags{ImageFlag<dimensions>(UnsignedShort(other._flags)&~UnsignedShort(ImageFlag2D::Array))|flags},
_size{Math::Vector<dimensions, Int>::pad(other._size, 1)},
_data{other._data} {}
#endif
template<UnsignedInt dimensions, class T> template<class U, class> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedImageView<dimensions, U>& other) noexcept: _storage{other._storage}, _format{other._format}, _flags{other._flags}, _size{other._size}, _data{other._data} {}
template<UnsignedInt dimensions, class T> template<class U, typename std::enable_if<std::is_const<T>::value && !std::is_const<U>::value, int>::type> CompressedImageView<dimensions, T>::CompressedImageView(const CompressedImageView<dimensions, U>& other) noexcept: _storage{other._storage}, _format{other._format}, _flags{other._flags}, _size{other._size}, _data{other._data} {}
#endif
}

6
src/Magnum/Math/Bezier.h

@ -119,11 +119,9 @@ template<UnsignedInt order, UnsignedInt dimensions, class T> class Bezier {
* inverse operation.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt order_ = order> static typename std::enable_if<order_ == 3, Bezier<order, dimensions, T>>::type
#else
static Bezier<order, dimensions, T>
template<UnsignedInt order_ = order, typename std::enable_if<order_ == 3, int>::type = 0>
#endif
fromCubicHermite(const CubicHermite<VectorType>& a, const CubicHermite<VectorType>& b) {
static Bezier<order, dimensions, T> fromCubicHermite(const CubicHermite<VectorType>& a, const CubicHermite<VectorType>& b) {
return {a.point(), a.outTangent()/T(3) - a.point(), b.point() - b.inTangent()/T(3), b.point()};
}

27
src/Magnum/Math/BitVector.h

@ -112,18 +112,25 @@ template<std::size_t size> class BitVector {
* @param first Value for first 8bit segment
* @param next Values for next Bbit segments
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class ...T> constexpr /*implicit*/ BitVector(UnsignedByte first, T... next) noexcept;
#else
template<class ...T, class U = typename std::enable_if<sizeof...(T)+1 == DataSize, bool>::type> constexpr /*implicit*/ BitVector(UnsignedByte first, T... next) noexcept: _data{first, UnsignedByte(next)...} {}
#endif
template<class ...T
#ifndef DOXYGEN_GENERATING_OUTPUT
/* For some reason MSVC 2015 and 2017 doesn't understand the value
parameter here, only a type parameter. Don't need to prevent any
ambiguity with this constructor so it's fine. */
#ifndef CORRADE_MSVC2017_COMPATIBILITY
, typename std::enable_if<sizeof...(T)+1 == DataSize, int>::type = 0
#else
, class = typename std::enable_if<sizeof...(T)+1 == DataSize>::type
#endif
#endif
> constexpr /*implicit*/ BitVector(UnsignedByte first, T... next) noexcept: _data{first, UnsignedByte(next)...} {}
/** @brief Construct a bit vector with one value for all fields */
#ifdef DOXYGEN_GENERATING_OUTPUT
explicit BitVector(T value) noexcept;
#else
template<class T, class U = typename std::enable_if<std::is_same<bool, T>::value && size != 1, bool>::type> constexpr explicit BitVector(T value) noexcept: BitVector(typename Containers::Implementation::GenerateSequence<DataSize>::Type{}, value ? FullSegmentMask : 0) {}
#endif
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_same<bool, T>::value && size != 1, int>::type = 0
#endif
> constexpr explicit BitVector(T value) noexcept: BitVector(typename Containers::Implementation::GenerateSequence<DataSize>::Type{}, value ? FullSegmentMask : 0) {}
/** @brief Construct a bit vector from external representation */
template<class U, class = decltype(Implementation::BitVectorConverter<size, U>::from(std::declval<U>()))> constexpr explicit BitVector(const U& other) noexcept: BitVector{Implementation::BitVectorConverter<size, U>::from(other)} {}

64
src/Magnum/Math/Color.h

@ -48,7 +48,7 @@ namespace Magnum { namespace Math {
namespace Implementation {
/* Convert color from HSV */
template<class T> typename std::enable_if<IsFloatingPoint<T>::value, Color3<T>>::type fromHsv(ColorHsv<T> hsv) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> Color3<T> fromHsv(ColorHsv<T> hsv) {
/* Remove repeats */
hsv.hue -= floor(T(hsv.hue)/T(360))*Deg<T>(360);
if(hsv.hue < Deg<T>(0)) hsv.hue += Deg<T>(360);
@ -70,7 +70,7 @@ template<class T> typename std::enable_if<IsFloatingPoint<T>::value, Color3<T>>:
default: CORRADE_INTERNAL_DEBUG_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
}
template<class T> inline typename std::enable_if<IsIntegral<T>::value, Color3<T>>::type fromHsv(const ColorHsv<typename TypeTraits<T>::FloatingPointType>& hsv) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline Color3<T> fromHsv(const ColorHsv<typename TypeTraits<T>::FloatingPointType>& hsv) {
return pack<Color3<T>>(fromHsv<typename TypeTraits<T>::FloatingPointType>(hsv));
}
@ -92,54 +92,54 @@ template<class T> Deg<T> hue(const Color3<T>& color, T max, T delta) {
}
/* Hue, saturation, value for floating-point types */
template<class T> inline Deg<T> hue(typename std::enable_if<IsFloatingPoint<T>::value, const Color3<T>&>::type color) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> inline Deg<T> hue(const Color3<T>& color) {
T max = color.max();
T delta = max - color.min();
return hue(color, max, delta);
}
template<class T> inline T saturation(typename std::enable_if<IsFloatingPoint<T>::value, const Color3<T>&>::type color) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> inline T saturation(const Color3<T>& color) {
T max = color.max();
T delta = max - color.min();
return max != T(0) ? delta/max : T(0);
}
template<class T> inline T value(typename std::enable_if<IsFloatingPoint<T>::value, const Color3<T>&>::type color) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> inline T value(const Color3<T>& color) {
return color.max();
}
/* Hue, saturation, value for integral types */
template<class T> inline Deg<typename Color3<T>::FloatingPointType> hue(typename std::enable_if<IsIntegral<T>::value, const Color3<T>&>::type color) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline Deg<typename Color3<T>::FloatingPointType> hue(const Color3<T>& color) {
return hue<typename Color3<T>::FloatingPointType>(unpack<Color3<typename Color3<T>::FloatingPointType>>(color));
}
template<class T> inline typename Color3<T>::FloatingPointType saturation(typename std::enable_if<IsIntegral<T>::value, const Color3<T>&>::type& color) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline typename Color3<T>::FloatingPointType saturation(const Color3<T>& color) {
return saturation<typename Color3<T>::FloatingPointType>(unpack<Color3<typename Color3<T>::FloatingPointType>>(color));
}
template<class T> inline typename Color3<T>::FloatingPointType value(typename std::enable_if<IsIntegral<T>::value, const Color3<T>&>::type color) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline typename Color3<T>::FloatingPointType value(const Color3<T>& color) {
return unpack<typename Color3<T>::FloatingPointType>(color.max());
}
/* Convert color to HSV */
template<class T> inline ColorHsv<T> toHsv(typename std::enable_if<IsFloatingPoint<T>::value, const Color3<T>&>::type color) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> inline ColorHsv<T> toHsv(const Color3<T>& color) {
T max = color.max();
T delta = max - color.min();
return ColorHsv<T>{hue<typename Color3<T>::FloatingPointType>(color, max, delta), max != T(0) ? delta/max : T(0), max};
}
template<class T> inline ColorHsv<typename TypeTraits<T>::FloatingPointType> toHsv(typename std::enable_if<IsIntegral<T>::value, const Color3<T>&>::type color) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline ColorHsv<typename TypeTraits<T>::FloatingPointType> toHsv(const Color3<T>& color) {
return toHsv<typename TypeTraits<T>::FloatingPointType>(unpack<Color3<typename TypeTraits<T>::FloatingPointType>>(color));
}
/* sRGB -> RGB conversion */
template<class T> typename std::enable_if<IsFloatingPoint<T>::value, Color3<T>>::type fromSrgb(const Vector3<T>& srgb) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> inline Color3<T> fromSrgb(const Vector3<T>& srgb) {
constexpr const T a(T(0.055));
return lerp(srgb/T(12.92), pow((srgb + Vector3<T>{a})/(T(1.0) + a), T(2.4)), srgb > Vector3<T>(T(0.04045)));
}
template<class T> typename std::enable_if<IsFloatingPoint<T>::value, Color4<T>>::type fromSrgbAlpha(const Vector4<T>& srgbAlpha) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> inline Color4<T> fromSrgbAlpha(const Vector4<T>& srgbAlpha) {
return {fromSrgb<T>(srgbAlpha.rgb()), srgbAlpha.a()};
}
template<class T> inline typename std::enable_if<IsIntegral<T>::value, Color3<T>>::type fromSrgb(const Vector3<typename Color3<T>::FloatingPointType>& srgb) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline Color3<T> fromSrgb(const Vector3<typename Color3<T>::FloatingPointType>& srgb) {
return pack<Color3<T>>(fromSrgb<typename Color3<T>::FloatingPointType>(srgb));
}
template<class T> inline typename std::enable_if<IsIntegral<T>::value, Color4<T>>::type fromSrgbAlpha(const Vector4<typename Color4<T>::FloatingPointType>& srgbAlpha) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline Color4<T> fromSrgbAlpha(const Vector4<typename Color4<T>::FloatingPointType>& srgbAlpha) {
return {fromSrgb<T>(srgbAlpha.rgb()), pack<T>(srgbAlpha.a())};
}
template<class T, class Integral> inline Color3<T> fromSrgbIntegral(const Vector3<Integral>& srgb) {
@ -152,23 +152,23 @@ template<class T, class Integral> inline Color4<T> fromSrgbAlphaIntegral(const V
}
/* Integer linear RGB -> linear RGB conversion */
template<class T> inline typename std::enable_if<IsFloatingPoint<T>::value, Color3<T>>::type fromLinearRgbInt(UnsignedInt linear) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> inline Color3<T> fromLinearRgbInt(UnsignedInt linear) {
return {unpack<T>(UnsignedByte(linear >> 16)),
unpack<T>(UnsignedByte(linear >> 8)),
unpack<T>(UnsignedByte(linear))};
}
template<class T> inline typename std::enable_if<IsFloatingPoint<T>::value, Color4<T>>::type fromLinearRgbaInt(UnsignedInt linear) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> inline Color4<T> fromLinearRgbaInt(UnsignedInt linear) {
return {unpack<T>(UnsignedByte(linear >> 24)),
unpack<T>(UnsignedByte(linear >> 16)),
unpack<T>(UnsignedByte(linear >> 8)),
unpack<T>(UnsignedByte(linear))};
}
template<class T> inline typename std::enable_if<IsIntegral<T>::value, Color3<T>>::type fromLinearRgbInt(UnsignedInt linear) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline Color3<T> fromLinearRgbInt(UnsignedInt linear) {
return {pack<T>(unpack<Float>(UnsignedByte(linear >> 16))),
pack<T>(unpack<Float>(UnsignedByte(linear >> 8))),
pack<T>(unpack<Float>(UnsignedByte(linear)))};
}
template<class T> inline typename std::enable_if<IsIntegral<T>::value, Color4<T>>::type fromLinearRgbaInt(UnsignedInt linear) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline Color4<T> fromLinearRgbaInt(UnsignedInt linear) {
return {pack<T>(unpack<Float>(UnsignedByte(linear >> 24))),
pack<T>(unpack<Float>(UnsignedByte(linear >> 16))),
pack<T>(unpack<Float>(UnsignedByte(linear >> 8))),
@ -176,17 +176,17 @@ template<class T> inline typename std::enable_if<IsIntegral<T>::value, Color4<T>
}
/* RGB -> sRGB conversion */
template<class T> Vector3<typename Color3<T>::FloatingPointType> toSrgb(typename std::enable_if<IsFloatingPoint<T>::value, const Color3<T>&>::type rgb) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> Vector3<typename Color3<T>::FloatingPointType> toSrgb(const Color3<T>& rgb) {
constexpr const T a = T(0.055);
return lerp(rgb*T(12.92), (T(1.0) + a)*pow(rgb, T(1.0)/T(2.4)) - Vector3<T>{a}, rgb > Vector3<T>(T(0.0031308)));
}
template<class T> Vector4<typename Color4<T>::FloatingPointType> toSrgbAlpha(typename std::enable_if<IsFloatingPoint<T>::value, const Color4<T>&>::type rgba) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> Vector4<typename Color4<T>::FloatingPointType> toSrgbAlpha(const Color4<T>& rgba) {
return {toSrgb<T>(rgba.rgb()), rgba.a()};
}
template<class T> inline Vector3<typename Color3<T>::FloatingPointType> toSrgb(typename std::enable_if<IsIntegral<T>::value, const Color3<T>&>::type rgb) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline Vector3<typename Color3<T>::FloatingPointType> toSrgb(const Color3<T>& rgb) {
return toSrgb<typename Color3<T>::FloatingPointType>(unpack<Color3<typename Color3<T>::FloatingPointType>>(rgb));
}
template<class T> inline Vector4<typename Color4<T>::FloatingPointType> toSrgbAlpha(typename std::enable_if<IsIntegral<T>::value, const Color4<T>&>::type rgba) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline Vector4<typename Color4<T>::FloatingPointType> toSrgbAlpha(const Color4<T>& rgba) {
return {toSrgb<T>(rgba.rgb()), unpack<typename Color3<T>::FloatingPointType>(rgba.a())};
}
template<class T, class Integral> inline Vector3<Integral> toSrgbIntegral(const Color3<T>& rgb) {
@ -199,23 +199,23 @@ template<class T, class Integral> inline Vector4<Integral> toSrgbAlphaIntegral(c
}
/* Linear RGB -> integer linear RGB conversion */
template<class T> inline typename std::enable_if<IsFloatingPoint<T>::value, UnsignedInt>::type toLinearRgbInt(const Color3<T>& linear) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> inline UnsignedInt toLinearRgbInt(const Color3<T>& linear) {
return (pack<UnsignedByte>(linear[0]) << 16) |
(pack<UnsignedByte>(linear[1]) << 8) |
pack<UnsignedByte>(linear[2]);
}
template<class T> inline typename std::enable_if<IsFloatingPoint<T>::value, UnsignedInt>::type toLinearRgbaInt(const Color4<T>& linear) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> inline UnsignedInt toLinearRgbaInt(const Color4<T>& linear) {
return (pack<UnsignedByte>(linear[0]) << 24) |
(pack<UnsignedByte>(linear[1]) << 16) |
(pack<UnsignedByte>(linear[2]) << 8) |
pack<UnsignedByte>(linear[3]);
}
template<class T> inline typename std::enable_if<IsIntegral<T>::value, UnsignedInt>::type toLinearRgbInt(const Color3<T>& linear) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline UnsignedInt toLinearRgbInt(const Color3<T>& linear) {
return (pack<UnsignedByte>(unpack<Float>(linear[0])) << 16) |
(pack<UnsignedByte>(unpack<Float>(linear[1])) << 8) |
pack<UnsignedByte>(unpack<Float>(linear[2]));
}
template<class T> inline typename std::enable_if<IsIntegral<T>::value, UnsignedInt>::type toLinearRgbaInt(const Color4<T>& linear) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline UnsignedInt toLinearRgbaInt(const Color4<T>& linear) {
return (pack<UnsignedByte>(unpack<Float>(linear[0])) << 24) |
(pack<UnsignedByte>(unpack<Float>(linear[1])) << 16) |
(pack<UnsignedByte>(unpack<Float>(linear[2])) << 8) |
@ -223,7 +223,7 @@ template<class T> inline typename std::enable_if<IsIntegral<T>::value, UnsignedI
}
/* CIE XYZ -> RGB conversion */
template<class T> typename std::enable_if<IsFloatingPoint<T>::value, Color3<T>>::type fromXyz(const Vector3<T>& xyz) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> Color3<T> fromXyz(const Vector3<T>& xyz) {
/* Taken from https://en.wikipedia.org/wiki/Talk:SRGB#Rounded_vs._Exact,
the rounded matrices from the main article don't round-trip perfectly */
return Matrix3x3<T>{
@ -231,12 +231,12 @@ template<class T> typename std::enable_if<IsFloatingPoint<T>::value, Color3<T>>:
Vector3<T>{T(-329)/T(214), T(1648619)/T(878810), T(-2585)/T(12673)},
Vector3<T>{T(-1974)/T(3959), T(36519)/T(878810), T(705)/T(667)}}*xyz;
}
template<class T> inline typename std::enable_if<IsIntegral<T>::value, Color3<T>>::type fromXyz(const Vector3<typename Color3<T>::FloatingPointType>& xyz) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline Color3<T> fromXyz(const Vector3<typename Color3<T>::FloatingPointType>& xyz) {
return pack<Color3<T>>(fromXyz<typename Color3<T>::FloatingPointType>(xyz));
}
/* RGB -> CIE XYZ conversion */
template<class T> Vector3<typename Color3<T>::FloatingPointType> toXyz(typename std::enable_if<IsFloatingPoint<T>::value, const Color3<T>&>::type rgb) {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> Vector3<typename Color3<T>::FloatingPointType> toXyz(const Color3<T>& rgb) {
/* Taken from https://en.wikipedia.org/wiki/Talk:SRGB#Rounded_vs._Exact,
the rounded matrices from the main article don't round-trip perfectly */
return (Matrix3x3<T>{
@ -244,7 +244,7 @@ template<class T> Vector3<typename Color3<T>::FloatingPointType> toXyz(typename
Vector3<T>{T(87881)/T(245763), T(175762)/T(245763), T(87881)/T(737289)},
Vector3<T>{T(12673)/T(70218), T(12673)/T(175545), T(1001167)/T(1053270)}})*rgb;
}
template<class T> inline Vector3<typename Color3<T>::FloatingPointType> toXyz(typename std::enable_if<IsIntegral<T>::value, const Color3<T>&>::type rgb) {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> inline Vector3<typename Color3<T>::FloatingPointType> toXyz(const Color3<T>& rgb) {
return toXyz<typename Color3<T>::FloatingPointType>(unpack<Color3<typename Color3<T>::FloatingPointType>>(rgb));
}
@ -256,10 +256,10 @@ template<class T> inline Vector3<typename Color3<T>::FloatingPointType> toXyz(ty
projects created directly using VS (enabled by default since 15.5) but not
projects using CMake. Not using SFINAE in this case makes it work. Minimal
repro case here: https://twitter.com/czmosra/status/1039446378248896513 */
template<class T> constexpr typename std::enable_if<IsFloatingPoint<T>::value, T>::type fullChannel() {
template<class T, typename std::enable_if<IsFloatingPoint<T>::value, int>::type = 0> constexpr T fullChannel() {
return T(1.0);
}
template<class T> constexpr typename std::enable_if<IsIntegral<T>::value, T>::type fullChannel() {
template<class T, typename std::enable_if<IsIntegral<T>::value, int>::type = 0> constexpr T fullChannel() {
return Implementation::bitMax<T>();
}
#else

17
src/Magnum/Math/CubicHermite.h

@ -88,13 +88,11 @@ template<class T> class CubicHermite {
* Enabled only on vector underlying types. See
* @ref Bezier::fromCubicHermite() for the inverse operation.
*/
template<UnsignedInt dimensions, class U> static
#ifdef DOXYGEN_GENERATING_OUTPUT
CubicHermite<T>
#else
typename std::enable_if<std::is_base_of<Vector<dimensions, U>, T>::value, CubicHermite<T>>::type
#endif
fromBezier(const CubicBezier<dimensions, U>& a, const CubicBezier<dimensions, U>& b) {
template<UnsignedInt dimensions, class U
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_base_of<Vector<dimensions, U>, T>::value, int>::type = 0
#endif
> static CubicHermite<T> fromBezier(const CubicBezier<dimensions, U>& a, const CubicBezier<dimensions, U>& b) {
return CORRADE_CONSTEXPR_DEBUG_ASSERT(a[3] == b[0],
"Math::CubicHermite::fromBezier(): segments are not adjacent"),
CubicHermite<T>{3*(a[3] - a[2]), a[3], 3*(b[1] - a[3])};
@ -124,7 +122,10 @@ template<class T> class CubicHermite {
* @ref outTangent() is constructed as zero. Enabled only for complex
* and quaternion types.
*/
template<class U = T, class = typename std::enable_if<std::is_constructible<U, IdentityInitT>::value>::type> constexpr explicit CubicHermite(IdentityInitT) noexcept: _inTangent{ZeroInit}, _point{IdentityInit}, _outTangent{ZeroInit} {}
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U = T, typename std::enable_if<std::is_constructible<U, IdentityInitT>::value, int>::type = 0>
#endif
constexpr explicit CubicHermite(IdentityInitT) noexcept: _inTangent{ZeroInit}, _point{IdentityInit}, _outTangent{ZeroInit} {}
/** @brief Construct a cubic Hermite spline point without initializing its contents */
explicit CubicHermite(Magnum::NoInitT) noexcept: CubicHermite{Magnum::NoInit, typename std::conditional<std::is_constructible<T, Magnum::NoInitT>::value, Magnum::NoInitT*, void*>::type{}} {}

31
src/Magnum/Math/Dual.h

@ -81,18 +81,17 @@ template<class T> class Dual {
#ifdef DOXYGEN_GENERATING_OUTPUT
constexpr explicit Dual(ZeroInitT) noexcept;
#else
/* MSVC 2015 can't handle {} instead of ::value */
template<class U = T, class = typename std::enable_if<std::is_standard_layout<U>::value && std::is_trivial<U>::value>::type> constexpr explicit Dual(ZeroInitT) noexcept: _real{}, _dual{} {}
template<class U = T, class V = T, class = typename std::enable_if<std::is_constructible<U, ZeroInitT>::value>::type> constexpr explicit Dual(ZeroInitT) noexcept: _real{ZeroInit}, _dual{ZeroInit} {}
template<class U = T, typename std::enable_if<std::is_standard_layout<U>::value && std::is_trivial<U>::value, int>::type = 0> constexpr explicit Dual(ZeroInitT) noexcept: _real{}, _dual{} {}
template<class U = T, typename std::enable_if<std::is_constructible<U, ZeroInitT>::value, int>::type = 0>
constexpr explicit Dual(ZeroInitT) noexcept: _real{ZeroInit}, _dual{ZeroInit} {}
#endif
/** @brief Construct without initializing the contents */
#ifdef DOXYGEN_GENERATING_OUTPUT
explicit Dual(NoInitT) noexcept;
#else
/* MSVC 2015 can't handle {} instead of ::value */
template<class U = T, class = typename std::enable_if<std::is_standard_layout<U>::value && std::is_trivial<U>::value>::type> explicit Dual(Magnum::NoInitT) noexcept {}
template<class U = T, class V = T, class = typename std::enable_if<std::is_constructible<U, Magnum::NoInitT>::value>::type> explicit Dual(Magnum::NoInitT) noexcept: _real{Magnum::NoInit}, _dual{Magnum::NoInit} {}
template<class U = T, typename std::enable_if<std::is_standard_layout<U>::value && std::is_trivial<U>::value, int>::type = 0> explicit Dual(Magnum::NoInitT) noexcept {}
template<class U = T, typename std::enable_if<std::is_constructible<U, Magnum::NoInitT>::value, int>::type = 0> explicit Dual(Magnum::NoInitT) noexcept: _real{Magnum::NoInit}, _dual{Magnum::NoInit} {}
#endif
/**
@ -275,7 +274,11 @@ template<class T> class Dual {
* @see @ref operator*(const Dual<U>&) const,
* @ref operator*(const T&, const Dual<U>&)
*/
template<class U, class V = typename std::enable_if<!Implementation::IsDual<U>::value, void>::type> Dual<decltype(std::declval<T>()*std::declval<U>())> operator*(const U& other) const {
template<class U
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!Implementation::IsDual<U>::value, int>::type = 0
#endif
> Dual<decltype(std::declval<T>()*std::declval<U>())> operator*(const U& other) const {
return {_real*other, _dual*other};
}
@ -287,7 +290,7 @@ template<class T> class Dual {
* @f]
* @see @ref operator/(const U&) const
*/
template<class U> auto operator/(const Dual<U>& other) const -> Dual<decltype(std::declval<T>()/std::declval<U>())> {
template<class U> Dual<decltype(std::declval<T>()/std::declval<U>())> operator/(const Dual<U>& other) const {
return {_real/other._real, (_dual*other._real - _real*other._dual)/(other._real*other._real)};
}
@ -300,7 +303,11 @@ template<class T> class Dual {
* @f]
* @see @ref operator/(const Dual<U>&) const
*/
template<class U, class V = typename std::enable_if<!Implementation::IsDual<U>::value, Dual<decltype(std::declval<T>()/std::declval<U>())>>::type> V operator/(const U& other) const {
template<class U,
#ifndef DOXYGEN_GENERATING_OUTPUT
typename std::enable_if<!Implementation::IsDual<U>::value, int>::type = 0
#endif
> Dual<decltype(std::declval<T>()/std::declval<U>())> operator/(const U& other) const {
return {_real/other, _dual/other};
}
@ -328,7 +335,11 @@ Equivalent to @ref Dual::operator*(const Dual<U>&) const assuming that
\hat a \hat b = a_0 b_0 + \epsilon (a_0 b_\epsilon + a_\epsilon b_0) = a_0 b_0 + \epsilon a_0 b_\epsilon
@f]
*/
template<class T, class U, class V = typename std::enable_if<!Implementation::IsDual<T>::value, Dual<decltype(std::declval<T>()*std::declval<U>())>>::type> inline V operator*(const T& a, const Dual<U>& b) {
template<class T, class U
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!Implementation::IsDual<T>::value, int>::type = 0
#endif
> inline Dual<decltype(std::declval<T>()*std::declval<U>())> operator*(const T& a, const Dual<U>& b) {
return {a*b.real(), a*b.dual()};
}

116
src/Magnum/Math/Functions.h

@ -252,7 +252,11 @@ the operations component-wise.
@see @ref isNan(), @ref Constants::inf(),
@ref isInf(const Containers::StridedArrayView1D<const T>&)
*/
template<class T> inline typename std::enable_if<IsScalar<T>::value, bool>::type isInf(T value) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline bool isInf(T value) {
return std::isinf(UnderlyingTypeOf<T>(value));
}
@ -276,7 +280,11 @@ Equivalent to @cpp value != value @ce.
@ref isNan(const Containers::StridedArrayView1D<const T>&)
*/
/* defined in Vector.h */
template<class T> typename std::enable_if<IsScalar<T>::value, bool>::type isNan(T value);
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type
#endif
> bool isNan(T value);
/**
@overload
@ -298,7 +306,11 @@ template<std::size_t size, class T> inline BitVector<size> isNan(const Vector<si
@ref Vector::min(), @ref Utility::min()
*/
/* defined in Vector.h */
template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type min(T value, T min);
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type
#endif
> constexpr T min(T value, T min);
/** @overload */
template<std::size_t size, class T> inline Vector<size, T> min(const Vector<size, T>& value, const Vector<size, T>& min) {
@ -325,7 +337,11 @@ template<std::size_t size, class T> inline Vector<size, T> min(const Vector<size
@ref Vector::max(), @ref Utility::max()
*/
/* defined in Vector.h */
template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type max(T a, T b);
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type
#endif
> constexpr T max(T a, T b);
/** @overload */
template<std::size_t size, class T> Vector<size, T> max(const Vector<size, T>& value, const Vector<size, T>& max) {
@ -351,7 +367,11 @@ template<std::size_t size, class T> inline Vector<size, T> max(const Vector<size
@ref Vector::minmax(),
@ref Range::Range(const Containers::Pair<VectorType, VectorType>&)
*/
template<class T> inline typename std::enable_if<IsScalar<T>::value, Containers::Pair<T, T>>::type minmax(T a, T b) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline Containers::Pair<T, T> minmax(T a, T b) {
return a < b ? Containers::pair(a, b) : Containers::pair(b, a);
}
@ -376,7 +396,11 @@ set to @p max. Equivalent to:
@see @ref min(), @ref max()
*/
/* defined in Vector.h */
template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type clamp(T value, T min, T max);
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type
#endif
> constexpr T clamp(T value, T min, T max);
/** @overload */
template<std::size_t size, class T> inline Vector<size, T> clamp(const Vector<size, T>& value, const Vector<size, T>& min, const Vector<size, T>& max) {
@ -399,7 +423,11 @@ template<std::size_t size, class T> inline Vector<size, T> clamp(const Vector<si
Returns `1` if @p x > 0, `0` if @p x = 0 and `-1` if @p x < 0.
*/
template<class T> inline typename std::enable_if<IsScalar<T>::value, UnderlyingTypeOf<T>>::type sign(T scalar) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline UnderlyingTypeOf<T> sign(T scalar) {
if(scalar > T(0)) return UnderlyingTypeOf<T>(1);
if(scalar < T(0)) return UnderlyingTypeOf<T>(-1);
return UnderlyingTypeOf<T>(0);
@ -414,7 +442,11 @@ template<std::size_t size, class T> inline Vector<size, UnderlyingTypeOf<T>> sig
}
/** @brief Absolute value */
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type abs(T a) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline T abs(T a) {
return T(std::abs(UnderlyingTypeOf<T>(a)));
}
@ -427,7 +459,11 @@ template<std::size_t size, class T> inline Vector<size, T> abs(const Vector<size
}
/** @brief Nearest not larger integer */
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type floor(T a) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline T floor(T a) {
return T(std::floor(UnderlyingTypeOf<T>(a)));
}
@ -440,7 +476,11 @@ template<std::size_t size, class T> inline Vector<size, T> floor(const Vector<si
}
/** @brief Round value to nearest integer */
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type round(T a) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline T round(T a) {
return T(std::round(UnderlyingTypeOf<T>(a)));
}
@ -453,7 +493,11 @@ template<std::size_t size, class T> inline Vector<size, T> round(const Vector<si
}
/** @brief Nearest not smaller integer */
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type ceil(T a) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline T ceil(T a) {
return T(std::ceil(UnderlyingTypeOf<T>(a)));
}
@ -481,7 +525,11 @@ Calculates the remainder @f$ r @f$ of a floating point division: @f[
@m_keyword{mod(),GLSL mod(),}
*/
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type fmod(T a, T b) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline T fmod(T a, T b) {
return T(std::fmod(UnderlyingTypeOf<T>(a), UnderlyingTypeOf<T>(b)));
}
@ -526,13 +574,11 @@ See @ref select() for constant interpolation using the same API and
@ref lerp(const CubicHermiteQuaternion<T>&, const CubicHermiteQuaternion<T>&, T)
@m_keyword{mix(),GLSL mix(),}
*/
template<class T, class U> inline
template<class T, class U
#ifndef DOXYGEN_GENERATING_OUTPUT
typename std::enable_if<(IsVector<T>::value || IsScalar<T>::value) && !Implementation::IsBitVectorOrScalar<U>::value, T>::type
#else
T
, typename std::enable_if<(IsVector<T>::value || IsScalar<T>::value) && !Implementation::IsBitVectorOrScalar<U>::value, int>::type = 0
#endif
lerp(const T& a, const T& b, U t) {
> inline T lerp(const T& a, const T& b, U t) {
return Implementation::lerp(a, b, t);
}
@ -587,7 +633,11 @@ expression combines that with @ref clamp() to ensure the value is in bounds:
@see @ref select()
*/
template<class T> inline UnderlyingTypeOf<typename std::enable_if<IsScalar<T>::value, T>::type> lerpInverted(T a, T b, T lerp) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline UnderlyingTypeOf<T> lerpInverted(T a, T b, T lerp) {
return (lerp - a)/(b - a);
}
@ -623,7 +673,11 @@ Computes and returns @f$ ab + c @f$. On some architectures might be faster than
doing the computation manually. Works only on types that satisfy
@ref IsUnitless.
*/
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type fma(T a, T b, T c) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline T fma(T a, T b, T c) {
static_assert(IsUnitless<T>::value, "expecting a unitless type");
/* On Emscripten it works with -O2 but not with -O1 (function not defined).
I guess that's only because -O2 optimizes it out, so disabling it there. */
@ -693,7 +747,11 @@ Returns integral power of base to the exponent. Works only on types that
satisfy @ref IsUnitless.
@see @ref pow(T, T)
*/
template<UnsignedInt exponent, class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type pow(T base) {
template<UnsignedInt exponent, class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> constexpr T pow(T base) {
static_assert(IsUnitless<T>::value, "expected a unitless type");
return Implementation::Pow<exponent>::pow(base);
}
@ -713,7 +771,11 @@ Returns power of @p base to the @p exponent. Works only on types that satisfy
@ref IsUnitless.
@see @ref pow(T), @ref exp()
*/
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type pow(T base, T exponent) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline T pow(T base, T exponent) {
static_assert(IsUnitless<T>::value, "expected a unitless type");
return std::pow(base, exponent);
}
@ -732,7 +794,11 @@ template<std::size_t size, class T> inline Vector<size, T> pow(const Vector<size
Works only on types that satisfy @ref IsUnitless.
@see @ref sqrtInverted(), @ref Vector::length(), @ref sqrt(const Dual<T>&)
*/
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type sqrt(T a) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline T sqrt(T a) {
static_assert(IsUnitless<T>::value, "expecting a unitless type");
return std::sqrt(a);
}
@ -752,7 +818,11 @@ Works only on types that satisfy @ref IsUnitless.
@see @ref sqrt(), @ref Vector::lengthInverted()
@m_keyword{inversesqrt(),GLSL inversesqrt(),}
*/
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type sqrtInverted(T a) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline T sqrtInverted(T a) {
static_assert(IsUnitless<T>::value, "expecting a unitless type");
return T(1)/std::sqrt(a);
}

2
src/Magnum/Math/FunctionsBatch.h

@ -292,7 +292,7 @@ template<class T, std::size_t size> inline T max(const T(&array)[size]) {
}
namespace Implementation {
template<class T> inline typename std::enable_if<IsScalar<T>::value, void>::type minmax(T& min, T& max, T value) {
template<class T, typename std::enable_if<IsScalar<T>::value, int>::type = 0> inline void minmax(T& min, T& max, T value) {
if(value < min)
min = value;
else if(value > max)

10
src/Magnum/Math/Packing.h

@ -82,14 +82,14 @@ representation to use. Example usage:
*/
template<class FloatingPoint, class Integral, UnsignedInt bits> inline FloatingPoint unpack(const Integral& value);
#else
template<class FloatingPoint, class Integral, UnsignedInt bits = sizeof(Integral)*8> inline typename std::enable_if<IsScalar<Integral>::value && std::is_unsigned<Integral>::value, FloatingPoint>::type unpack(const Integral& value) {
template<class FloatingPoint, class Integral, UnsignedInt bits = sizeof(Integral)*8, typename std::enable_if<IsScalar<Integral>::value && std::is_unsigned<Integral>::value, int>::type = 0> inline FloatingPoint unpack(const Integral& value) {
static_assert(IsFloatingPoint<FloatingPoint>::value && IsIntegral<Integral>::value,
"unpacking must be done from integral to floating-point type");
static_assert(bits <= sizeof(Integral)*8,
"bit count larger than size of the integral type");
return FloatingPoint(value/UnderlyingTypeOf<FloatingPoint>(Implementation::bitMax<Integral, bits>()));
}
template<class FloatingPoint, class Integral, UnsignedInt bits = sizeof(Integral)*8> inline typename std::enable_if<IsScalar<Integral>::value && std::is_signed<Integral>::value, FloatingPoint>::type unpack(const Integral& value) {
template<class FloatingPoint, class Integral, UnsignedInt bits = sizeof(Integral)*8, typename std::enable_if<IsScalar<Integral>::value && std::is_signed<Integral>::value, int>::type = 0> inline FloatingPoint unpack(const Integral& value) {
static_assert(IsFloatingPoint<FloatingPoint>::value && IsIntegral<Integral>::value,
"unpacking must be done from integral to floating-point type");
static_assert(bits <= sizeof(Integral)*8,
@ -111,7 +111,7 @@ template<class FloatingPoint, std::size_t size, class Integral, UnsignedInt bits
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint, UnsignedInt bits, class Integral> inline FloatingPoint unpack(const Integral& value);
#else
template<class FloatingPoint, UnsignedInt bits, class Integral> inline typename std::enable_if<IsScalar<Integral>::value, FloatingPoint>::type unpack(const Integral& value) {
template<class FloatingPoint, UnsignedInt bits, class Integral, typename std::enable_if<IsScalar<Integral>::value, int>::type = 0> inline FloatingPoint unpack(const Integral& value) {
return unpack<FloatingPoint, Integral, bits>(value);
}
template<class FloatingPoint, UnsignedInt bits, std::size_t size, class Integral> inline FloatingPoint unpack(const Vector<size, Integral>& value) {
@ -139,7 +139,7 @@ given *signed* integral type.
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class Integral, class FloatingPoint> inline Integral pack(const FloatingPoint& value);
#else
template<class Integral, class FloatingPoint, UnsignedInt bits = sizeof(Integral)*8> inline typename std::enable_if<IsScalar<FloatingPoint>::value, Integral>::type pack(FloatingPoint value) {
template<class Integral, class FloatingPoint, UnsignedInt bits = sizeof(Integral)*8, typename std::enable_if<IsScalar<FloatingPoint>::value, int>::type = 0> inline Integral pack(FloatingPoint value) {
static_assert(IsFloatingPoint<FloatingPoint>::value && IsIntegral<Integral>::value,
"packing must be done from floating-point to integral type");
static_assert(bits <= sizeof(Integral)*8,
@ -167,7 +167,7 @@ representation to use. Example usage:
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class Integral, UnsignedInt bits, class FloatingPoint> inline Integral pack(FloatingPoint value);
#else
template<class Integral, UnsignedInt bits, class FloatingPoint> inline typename std::enable_if<IsScalar<FloatingPoint>::value, Integral>::type pack(FloatingPoint value) {
template<class Integral, UnsignedInt bits, class FloatingPoint, typename std::enable_if<IsScalar<FloatingPoint>::value, int>::type = 0> inline Integral pack(FloatingPoint value) {
return pack<Integral, FloatingPoint, bits>(value);
}
template<class Integral, UnsignedInt bits, std::size_t size, class FloatingPoint> inline Integral pack(const Vector<size, FloatingPoint>& value) {

8
src/Magnum/Math/Range.h

@ -144,7 +144,7 @@ template<UnsignedInt dimensions, class T> class Range {
constexpr /*implicit*/ Range(const VectorType& min, const VectorType& max) noexcept: _min{min}, _max{max} {}
/** @overload */
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d == 1>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d == 1, int>::type = 0>
#endif
constexpr /*implicit*/ Range(const Vector<dimensions, T>& min, const Vector<dimensions, T>& max) noexcept: _min{Implementation::RangeTraits<dimensions, T>::fromVector(min)}, _max{Implementation::RangeTraits<dimensions, T>::fromVector(max)} {}
@ -161,7 +161,7 @@ template<UnsignedInt dimensions, class T> class Range {
/** @overload */
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d != 1>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d != 1, int>::type = 0>
#endif
constexpr /*implicit*/ Range(const Containers::Pair<Vector<dimensions, T>, Vector<dimensions, T>>& minmax) noexcept: _min{minmax.first()}, _max{minmax.second()} {}
@ -311,7 +311,7 @@ template<UnsignedInt dimensions, class T> class Range {
* @m_since_latest
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d != 1>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d != 1, int>::type = 0>
#endif
Range<dimensions, T> scaled(T scaling) const {
return {_min*scaling, _max*scaling};
@ -334,7 +334,7 @@ template<UnsignedInt dimensions, class T> class Range {
* @m_since_latest
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt d = dimensions, class = typename std::enable_if<d != 1>::type>
template<UnsignedInt d = dimensions, typename std::enable_if<d != 1, int>::type = 0>
#endif
Range<dimensions, T> scaledFromCenter(T scaling) const {
/* Can't use *T(0.5) because that won't work for integers */

4
src/Magnum/Math/Test/TypeTraitsTest.cpp

@ -359,10 +359,10 @@ template<class T> void TypeTraitsTest::equalsFloatingPointNaN() {
}
/* Argh! Why there is no standard std::abs() for unsigned types? */
template<class T, class U = typename std::enable_if<std::is_unsigned<T>::value>::type> T abs(T value) {
template<class T, typename std::enable_if<std::is_unsigned<T>::value, int>::type = 0> T abs(T value) {
return value;
}
template<class T, class U = T, class V = typename std::enable_if<!std::is_unsigned<T>::value>::type> T abs(T value) {
template<class T, typename std::enable_if<!std::is_unsigned<T>::value, int>::type = 0> T abs(T value) {
return std::abs(value);
}

12
src/Magnum/Math/TypeTraits.h

@ -405,7 +405,11 @@ Calls @ref TypeTraits<T>::equals() --- using fuzzy compare for floating-point
types and doing equality comparison on integral types. Scalar complement to
@ref equal(const Vector<size, T>& a, const Vector<size, T>&).
*/
template<class T> inline typename std::enable_if<IsScalar<T>::value, bool>::type equal(T a, T b) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline bool equal(T a, T b) {
return TypeTraits<T>::equals(a, b);
}
@ -417,7 +421,11 @@ Calls @ref TypeTraits<T>::equals() --- using fuzzy compare for floating-point
types and doing equality comparison on integral types. Scalar complement to
@ref notEqual(const Vector<size, T>& a, const Vector<size, T>&).
*/
template<class T> inline typename std::enable_if<IsScalar<T>::value, bool>::type notEqual(T a, T b) {
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<IsScalar<T>::value, int>::type = 0
#endif
> inline bool notEqual(T a, T b) {
return !TypeTraits<T>::equals(a, b);
}

73
src/Magnum/Math/Unit.h

@ -178,12 +178,11 @@ template<template<class> class Derived, class T> class Unit {
* Similar to @ref operator*=(T), except that the multiplication is
* done in floating-point.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint> Unit<Derived, T>&
#else
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Unit<Derived, T>&>::type
#endif
operator*=(FloatingPoint number) {
template<class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> Unit<Derived, T>& operator*=(FloatingPoint number) {
_value = T(_value*number);
return *this;
}
@ -199,12 +198,11 @@ template<template<class> class Derived, class T> class Unit {
an out-of-class overload wrapped in CORRADE_MSVC2015_COMPATIBILITY
which is (and the two don't conflict, apparently, so both are
present) */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint> constexpr Unit<Derived, T>
#else
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Unit<Derived, T>>::type
#endif
operator*(FloatingPoint number) const {
template<class FloatingPoint, class Integral = T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> constexpr Unit<Derived, T> operator*(FloatingPoint number) const {
return Unit<Derived, T>{T(_value*number)};
}
@ -214,12 +212,11 @@ template<template<class> class Derived, class T> class Unit {
*
* Same as @ref operator*(FloatingPoint) const.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint> friend constexpr Unit<Derived, T>
#else
template<class FloatingPoint, class Integral = T> friend constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Unit<Derived, T>>::type
#endif
operator*(FloatingPoint number, const Unit<Derived, T>& value) {
template<class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> friend constexpr Unit<Derived, T> operator*(FloatingPoint number, const Unit<Derived, T>& value) {
return Unit<Derived, T>{T(value._value*number)};
}
@ -241,12 +238,11 @@ template<template<class> class Derived, class T> class Unit {
* Similar to @ref operator/=(T), except that the division is done in
* floating-point.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint> Unit<Derived, T>&
#else
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Unit<Derived, T>&>::type
#endif
operator/=(FloatingPoint number) {
template<class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> Unit<Derived, T>& operator/=(FloatingPoint number) {
_value = T(_value/number);
return *this;
}
@ -258,12 +254,11 @@ template<template<class> class Derived, class T> class Unit {
* Similar to @ref operator/(T) const, except that the division is done
* in floating-point.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint> constexpr Unit<Derived, T>
#else
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Unit<Derived, T>>::type
#endif
operator/(FloatingPoint number) const {
template<class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> constexpr Unit<Derived, T> operator/(FloatingPoint number) const {
return Unit<Derived, T>{T(_value/number)};
}
@ -278,12 +273,10 @@ template<template<class> class Derived, class T> class Unit {
*
* Enabled only for integral types.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
Unit<Derived, T>&
#else
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Unit<Derived, T>&>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
#endif
operator%=(Unit<Derived, T> other) {
Unit<Derived, T>& operator%=(Unit<Derived, T> other) {
_value %= other._value;
return *this;
}
@ -294,12 +287,10 @@ template<template<class> class Derived, class T> class Unit {
*
* Enabled only for integral types.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
constexpr Unit<Derived, T>
#else
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Unit<Derived, T>>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
#endif
operator%(Unit<Derived, T> other) const {
constexpr Unit<Derived, T> operator%(Unit<Derived, T> other) const {
return Unit<Derived, T>{_value%other._value};
}
@ -314,7 +305,7 @@ template<template<class> class Derived, class T> class Unit {
picked up correctly (and doesn't conflict with the in-class one). See
UnitTest::multiplyDivideIntegral() for regression tests, the same issue and
a matching workaround is done in Vector as well. */
template<template<class> class Derived, class FloatingPoint, class Integral> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Unit<Derived, Integral>>::type operator*(FloatingPoint number, const Unit<Derived, Integral>& value) {
template<template<class> class Derived, class FloatingPoint, class Integral, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0> constexpr Unit<Derived, Integral> operator*(FloatingPoint number, const Unit<Derived, Integral>& value) {
return value*number;
}
#endif

342
src/Magnum/Math/Vector.h

@ -55,18 +55,18 @@ namespace Magnum { namespace Math {
#ifndef DOXYGEN_GENERATING_OUTPUT
/* Documented in Functions.h, defined here because Vector needs them */
template<class T> inline typename std::enable_if<IsScalar<T>::value, bool>::type isNan(T value) {
template<class T, typename std::enable_if<IsScalar<T>::value, int>::type = 0> inline bool isNan(T value) {
return std::isnan(UnderlyingTypeOf<T>(value));
}
/* Keeping the same parameter names as in Functions.h so the note about
NaN propagation works here too */
template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type min(T value, T min) {
template<class T, typename std::enable_if<IsScalar<T>::value, int>::type = 0> constexpr T min(T value, T min) {
return min < value ? min : value;
}
template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type max(T value, T max) {
template<class T, typename std::enable_if<IsScalar<T>::value, int>::type = 0> constexpr T max(T value, T max) {
return value < max ? max : value;
}
template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type clamp(T value, T min, T max) {
template<class T, typename std::enable_if<IsScalar<T>::value, int>::type = 0> constexpr T clamp(T value, T min, T max) {
return Math::min(Math::max(value, min), max);
}
#endif
@ -139,13 +139,11 @@ dot product is clamped to the @f$ [-1, +1] @f$ range before being passed to
@ref angle(const Complex<T>&, const Complex<T>&),
@ref angle(const Quaternion<T>&, const Quaternion<T>&)
*/
template<std::size_t size, class FloatingPoint> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Rad<FloatingPoint>
#else
typename std::enable_if<std::is_floating_point<FloatingPoint>::value, Rad<FloatingPoint>>::type
#endif
angle(const Vector<size, FloatingPoint>& normalizedA, const Vector<size, FloatingPoint>& normalizedB) {
template<std::size_t size, class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> inline Rad<FloatingPoint> angle(const Vector<size, FloatingPoint>& normalizedA, const Vector<size, FloatingPoint>& normalizedB) {
CORRADE_DEBUG_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(),
"Math::angle(): vectors" << normalizedA << "and" << normalizedB << "are not normalized", {});
return Rad<FloatingPoint>(std::acos(clamp(dot(normalizedA, normalizedB), FloatingPoint(-1), FloatingPoint(1))));
@ -217,11 +215,11 @@ template<std::size_t size, class T> class Vector {
explicit Vector(Magnum::NoInitT) noexcept {}
/** @brief Construct a vector from components */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class ...U> constexpr /*implicit*/ Vector(T first, U... next) noexcept;
#else
template<class ...U, class V = typename std::enable_if<sizeof...(U)+1 == size, T>::type> constexpr /*implicit*/ Vector(T first, U... next) noexcept: _data{first, next...} {}
#endif
template<class ...U
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<sizeof...(U)+1 == size, int>::type = 0
#endif
> constexpr /*implicit*/ Vector(T first, U... next) noexcept: _data{first, next...} {}
/**
* @brief Construct a vector from a fixed-size array
@ -243,9 +241,9 @@ template<std::size_t size, class T> class Vector {
/** @brief Construct a vector with one value for all components */
#ifdef DOXYGEN_GENERATING_OUTPUT
constexpr explicit Vector(T value) noexcept;
constexpr explicit Vector(T value) noexcept; /* showing T instead of U */
#else
template<class U, class V = typename std::enable_if<std::is_same<T, U>::value && size != 1, T>::type> constexpr explicit Vector(U value) noexcept: Vector(typename Containers::Implementation::GenerateSequence<size>::Type{}, value) {}
template<class U, typename std::enable_if<std::is_same<T, U>::value && size != 1, int>::type = 0> constexpr explicit Vector(U value) noexcept: Vector(typename Containers::Implementation::GenerateSequence<size>::Type{}, value) {}
#endif
/**
@ -399,12 +397,10 @@ template<std::size_t size, class T> class Vector {
* @f]
* @see @ref flipped(), @ref Vector2::perpendicular()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
constexpr Vector<size, T>
#else
template<class U = T> constexpr typename std::enable_if<std::is_signed<U>::value, Vector<size, T>>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U = T, typename std::enable_if<std::is_signed<U>::value, int>::type = 0>
#endif
operator-() const {
constexpr Vector<size, T> operator-() const {
return negateInternal(typename Containers::Implementation::GenerateSequence<size>::Type{});
}
@ -503,12 +499,11 @@ template<std::size_t size, class T> class Vector {
* Similar to @ref operator*=(T), except that the multiplication is
* done in floating-point. The computation is done in-place.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint> Vector<size, T>&
#else
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>&>::type
#endif
operator*=(FloatingPoint scalar) {
template<class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> Vector<size, T>& operator*=(FloatingPoint scalar) {
for(std::size_t i = 0; i != size; ++i)
_data[i] = T(_data[i]*scalar);
@ -521,12 +516,11 @@ template<std::size_t size, class T> class Vector {
* Similar to @ref operator*(T) const, except that the multiplication
* is done in floating-point.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint> constexpr Vector<size, T>
#else
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>>::type
#endif
operator*(FloatingPoint scalar) const {
template<class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> constexpr Vector<size, T> operator*(FloatingPoint scalar) const {
return multiplyIntegerInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{});
}
@ -539,11 +533,11 @@ template<std::size_t size, class T> class Vector {
an out-of-class overload wrapped in CORRADE_MSVC2015_COMPATIBILITY
which is (and the two don't conflict, apparently, so both are
present) */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint> friend constexpr Vector<size, T>
#else
template<class FloatingPoint, class Integral = T> friend constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>>::type
#endif
template<class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> friend constexpr Vector<size, T>
operator*(FloatingPoint scalar, const Vector<size, T>& vector) {
return vector*scalar;
}
@ -600,12 +594,11 @@ template<std::size_t size, class T> class Vector {
* Similar to @ref operator/=(T), except that the division is done in
* floating-point. The computation is done in-place.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint> Vector<size, Integral>&
#else
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>&>::type
#endif
operator/=(FloatingPoint scalar) {
template<class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> Vector<size, T>& operator/=(FloatingPoint scalar) {
for(std::size_t i = 0; i != size; ++i)
_data[i] = T(_data[i]/scalar);
@ -618,12 +611,11 @@ template<std::size_t size, class T> class Vector {
* Similar to @ref operator/(T) const, except that the division is done
* in floating-point.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint> Vector<size, T> constexpr
#else
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>>::type
#endif
operator/(FloatingPoint scalar) const {
template<class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> constexpr Vector<size, T> operator/(FloatingPoint scalar) const {
return divideIntegerInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{});
}
@ -661,12 +653,11 @@ template<std::size_t size, class T> class Vector {
* multiplication is done in floating-point. The computation is done
* in-place.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint> Vector<size, T>&
#else
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>&>::type
#endif
operator*=(const Vector<size, FloatingPoint>& other) {
template<class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> Vector<size, T>& operator*=(const Vector<size, FloatingPoint>& other) {
for(std::size_t i = 0; i != size; ++i)
_data[i] = T(_data[i]*other._data[i]);
@ -683,7 +674,7 @@ template<std::size_t size, class T> class Vector {
*/
template<class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value>::type* = nullptr
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> constexpr Vector<size, T> operator*(const Vector<size, FloatingPoint>& other) const {
return multiplyIntegerInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
@ -701,7 +692,7 @@ template<std::size_t size, class T> class Vector {
Integral*FloatingPoint variant above */
template<class Integral
#ifndef DOXYGEN_GENERATING_OUTPUT
, class FloatingPoint = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value>::type* = nullptr
, class FloatingPoint = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> constexpr Vector<size, Integral> operator*(const Vector<size, Integral>& other) const {
return other**this;
@ -740,12 +731,11 @@ template<std::size_t size, class T> class Vector {
* division is done in floating-point. The computation is done
* in-place.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint> Vector<size, T>&
#else
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>&>::type
#endif
operator/=(const Vector<size, FloatingPoint>& other) {
template<class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> Vector<size, T>& operator/=(const Vector<size, FloatingPoint>& other) {
for(std::size_t i = 0; i != size; ++i)
_data[i] = T(_data[i]/other._data[i]);
@ -760,12 +750,11 @@ template<std::size_t size, class T> class Vector {
* always an integral vector, convert both arguments to the same
* floating-point type to have a floating-point result.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint> constexpr Vector<size, T>
#else
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, T>>::type
#endif
operator/(const Vector<size, FloatingPoint>& other) const {
template<class FloatingPoint
#ifndef DOXYGEN_GENERATING_OUTPUT
, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0
#endif
> constexpr Vector<size, T> operator/(const Vector<size, FloatingPoint>& other) const {
return divideIntegerInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
}
@ -774,12 +763,10 @@ template<std::size_t size, class T> class Vector {
*
* Enabled only for integral types. The computation is done in-place.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, T>&
#else
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
#endif
operator%=(T scalar) {
Vector<size, T>& operator%=(T scalar) {
for(std::size_t i = 0; i != size; ++i)
_data[i] %= scalar;
@ -791,12 +778,10 @@ template<std::size_t size, class T> class Vector {
*
* Enabled only for integral types.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
constexpr Vector<size, T>
#else
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
#endif
operator%(T scalar) const {
constexpr Vector<size, T> operator%(T scalar) const {
return moduloInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{});
}
@ -805,12 +790,10 @@ template<std::size_t size, class T> class Vector {
*
* Enabled only for integral types. The computation is done in-place.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, T>&
#else
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
#endif
operator%=(const Vector<size, T>& other) {
Vector<size, T>& operator%=(const Vector<size, T>& other) {
for(std::size_t i = 0; i != size; ++i)
_data[i] %= other._data[i];
@ -822,12 +805,10 @@ template<std::size_t size, class T> class Vector {
*
* Enabled only for integral types.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
constexpr Vector<size, T>
#else
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
#endif
operator%(const Vector<size, T>& other) const {
constexpr Vector<size, T> operator%(const Vector<size, T>& other) const {
return moduloInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
}
@ -836,12 +817,10 @@ template<std::size_t size, class T> class Vector {
*
* Enabled only for integral types.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
constexpr Vector<size, T>
#else
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
#endif
operator~() const {
constexpr Vector<size, T> operator~() const {
return invertInternal(typename Containers::Implementation::GenerateSequence<size>::Type{});
}
@ -850,12 +829,10 @@ template<std::size_t size, class T> class Vector {
*
* Enabled only for integral types. The computation is done in-place.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, T>&
#else
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
#endif
operator&=(const Vector<size, T>& other) {
Vector<size, T>& operator&=(const Vector<size, T>& other) {
for(std::size_t i = 0; i != size; ++i)
_data[i] &= other._data[i];
@ -867,12 +844,10 @@ template<std::size_t size, class T> class Vector {
*
* Enabled only for integral types.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
constexpr Vector<size, T>
#else
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
#endif
operator&(const Vector<size, T>& other) const {
constexpr Vector<size, T> operator&(const Vector<size, T>& other) const {
return andInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
}
@ -881,12 +856,10 @@ template<std::size_t size, class T> class Vector {
*
* Enabled only for integral types. The computation is done in-place.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, T>&
#else
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
#endif
operator|=(const Vector<size, T>& other) {
Vector<size, T>& operator|=(const Vector<size, T>& other) {
for(std::size_t i = 0; i != size; ++i)
_data[i] |= other._data[i];
@ -898,12 +871,10 @@ template<std::size_t size, class T> class Vector {
*
* Enabled only for integral types.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
constexpr Vector<size, T>
#else
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
#endif
operator|(const Vector<size, T>& other) const {
constexpr Vector<size, T> operator|(const Vector<size, T>& other) const {
return orInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
}
@ -912,12 +883,10 @@ template<std::size_t size, class T> class Vector {
*
* Enabled only for integral types. The computation is done in-place.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, T>&
#else
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
#endif
operator^=(const Vector<size, T>& other) {
Vector<size, T>& operator^=(const Vector<size, T>& other) {
for(std::size_t i = 0; i != size; ++i)
_data[i] ^= other._data[i];
@ -929,12 +898,10 @@ template<std::size_t size, class T> class Vector {
*
* Enabled only for integral types.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
constexpr Vector<size, T>
#else
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
#endif
operator^(const Vector<size, T>& other) const {
constexpr Vector<size, T> operator^(const Vector<size, T>& other) const {
return xorInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{});
}
@ -946,7 +913,7 @@ template<std::size_t size, class T> class Vector {
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, T>& operator<<=(T shift)
#else
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type operator<<=(typename std::common_type<T>::type shift)
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> Vector<size, T>& operator<<=(typename std::common_type<T>::type shift)
#endif
{
for(std::size_t i = 0; i != size; ++i)
@ -963,8 +930,7 @@ template<std::size_t size, class T> class Vector {
#ifdef DOXYGEN_GENERATING_OUTPUT
constexpr Vector<size, T> operator<<(T shift) const
#else
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type
operator<<(typename std::common_type<T>::type shift) const
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> constexpr Vector<size, T> operator<<(typename std::common_type<T>::type shift) const
#endif
{
return shiftLeftInternal(shift, typename Containers::Implementation::GenerateSequence<size>::Type{});
@ -978,7 +944,7 @@ template<std::size_t size, class T> class Vector {
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, T>& operator>>=(T shift)
#else
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>&>::type operator>>=(typename std::common_type<T>::type shift)
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> Vector<size, T>& operator>>=(typename std::common_type<T>::type shift)
#endif
{
for(std::size_t i = 0; i != size; ++i)
@ -995,8 +961,8 @@ template<std::size_t size, class T> class Vector {
#ifdef DOXYGEN_GENERATING_OUTPUT
constexpr Vector<size, T> operator>>(T shift) const
#else
template<class Integral = T>
constexpr typename std::enable_if<std::is_integral<Integral>::value, Vector<size, T>>::type operator>>(typename std::common_type<T>::type shift) const
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0>
constexpr Vector<size, T> operator>>(typename std::common_type<T>::type shift) const
#endif
{
return shiftRightInternal(shift, typename Containers::Implementation::GenerateSequence<size>::Type{});
@ -1051,12 +1017,10 @@ template<std::size_t size, class T> class Vector {
* @see @ref length(), @ref Math::sqrtInverted(), @ref normalized(),
* @ref resized()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
T
#else
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, T>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U = T, typename std::enable_if<std::is_floating_point<U>::value, int>::type = 0>
#endif
lengthInverted() const { return T(1)/length(); }
T lengthInverted() const { return T(1)/length(); }
/**
* @brief Normalized vector (of unit length)
@ -1065,12 +1029,10 @@ template<std::size_t size, class T> class Vector {
* @see @ref isNormalized(), @ref lengthInverted(), @ref resized()
* @m_keyword{normalize(),GLSL normalize(),}
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, T>
#else
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Vector<size, T>>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U = T, typename std::enable_if<std::is_floating_point<U>::value, int>::type = 0>
#endif
normalized() const { return *this*lengthInverted(); }
Vector<size, T> normalized() const { return *this*lengthInverted(); }
/**
* @brief Resized vector
@ -1083,12 +1045,10 @@ template<std::size_t size, class T> class Vector {
*
* @see @ref normalized()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, T>
#else
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Vector<size, T>>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U = T, typename std::enable_if<std::is_floating_point<U>::value, int>::type = 0>
#endif
resized(T length) const {
Vector<size, T> resized(T length) const {
return *this*(lengthInverted()*length);
}
@ -1101,12 +1061,10 @@ template<std::size_t size, class T> class Vector {
* @f]
* @see @ref Math::dot(), @ref projectedOntoNormalized()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, T>
#else
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Vector<size, T>>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U = T, typename std::enable_if<std::is_floating_point<U>::value, int>::type = 0>
#endif
projected(const Vector<size, T>& line) const {
Vector<size, T> projected(const Vector<size, T>& line) const {
return line*Math::dot(*this, line)/line.dot();
}
@ -1121,11 +1079,10 @@ template<std::size_t size, class T> class Vector {
* @see @ref Math::dot()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, T>
#else
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Vector<size, T>>::type
template<class U = T, typename std::enable_if<std::is_floating_point<U>::value, int>::type = 0>
#endif
projectedOntoNormalized(const Vector<size, T>& line) const;
Vector<size, T> projectedOntoNormalized(const Vector<size, T>& line) const;
/**
* @brief Flipped vector
@ -1398,8 +1355,7 @@ extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<4, Double>&
constexpr Type_<T> operator+() const { \
return Math::Vector<size, T>::operator+(); \
} \
template<class U = T> constexpr typename std::enable_if<std::is_signed<U>::value, Type_<T>>::type \
operator-() const { \
template<class U = T, typename std::enable_if<std::is_signed<U>::value, int>::type = 0> constexpr Type_<T> operator-() const { \
return Math::Vector<size, T>::negateInternal(typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
Type_<T>& operator+=(const Math::Vector<size, T>& other) { \
@ -1427,14 +1383,14 @@ extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<4, Double>&
friend constexpr Type_<T> operator*(typename std::common_type<T>::type scalar, const Type_<T>& vector) { \
return scalar*static_cast<const Math::Vector<size, T>&>(vector); \
} \
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>&>::type operator*=(FloatingPoint scalar) { \
template<class FloatingPoint, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0> Type_<T>& operator*=(FloatingPoint scalar) { \
Math::Vector<size, T>::operator*=(scalar); \
return *this; \
} \
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>>::type operator*(FloatingPoint scalar) const { \
template<class FloatingPoint, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0> constexpr Type_<T> operator*(FloatingPoint scalar) const { \
return Math::Vector<size, T>::multiplyIntegerInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
template<class FloatingPoint, class Integral = T> friend constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>>::type operator*(FloatingPoint scalar, const Type_<T>& vector) { \
template<class FloatingPoint, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0> friend constexpr Type_<T> operator*(FloatingPoint scalar, const Type_<T>& vector) { \
return scalar*static_cast<const Math::Vector<size, T>&>(vector); \
} \
\
@ -1448,11 +1404,11 @@ extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<4, Double>&
friend constexpr Type_<T> operator/(typename std::common_type<T>::type scalar, const Type_<T>& vector) { \
return scalar/static_cast<const Math::Vector<size, T>&>(vector); \
} \
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>&>::type operator/=(FloatingPoint scalar) { \
template<class FloatingPoint, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0> Type_<T>& operator/=(FloatingPoint scalar) { \
Math::Vector<size, T>::operator/=(scalar); \
return *this; \
} \
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>>::type operator/(FloatingPoint scalar) const { \
template<class FloatingPoint, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0> constexpr Type_<T> operator/(FloatingPoint scalar) const { \
return Math::Vector<size, T>::divideIntegerInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
\
@ -1463,14 +1419,14 @@ extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<4, Double>&
constexpr Type_<T> operator*(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::multiplyInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>&>::type operator*=(const Math::Vector<size, FloatingPoint>& other) { \
template<class FloatingPoint, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0> Type_<T>& operator*=(const Math::Vector<size, FloatingPoint>& other) { \
Math::Vector<size, T>::operator*=(other); \
return *this; \
} \
template<class FloatingPoint, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value>::type* = nullptr> constexpr Type_<T> operator*(const Math::Vector<size, FloatingPoint>& other) const { \
template<class FloatingPoint, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0> constexpr Type_<T> operator*(const Math::Vector<size, FloatingPoint>& other) const { \
return Math::Vector<size, T>::multiplyIntegerInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
template<class Integral, class FloatingPoint = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value>::type* = nullptr> constexpr Type_<Integral> operator*(const Math::Vector<size, Integral>& other) const { \
template<class Integral, class FloatingPoint = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0> constexpr Type_<Integral> operator*(const Math::Vector<size, Integral>& other) const { \
return other**this; \
} \
\
@ -1481,78 +1437,78 @@ extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<4, Double>&
constexpr Type_<T> operator/(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::divideInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>&>::type operator/=(const Math::Vector<size, FloatingPoint>& other) { \
template<class FloatingPoint, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0> Type_<T>& operator/=(const Math::Vector<size, FloatingPoint>& other) { \
Math::Vector<size, T>::operator/=(other); \
return *this; \
} \
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type_<T>>::type operator/(const Math::Vector<size, FloatingPoint>& other) const { \
template<class FloatingPoint, class Integral = T, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0> constexpr Type_<T> operator/(const Math::Vector<size, FloatingPoint>& other) const { \
return Math::Vector<size, T>::divideIntegerInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
\
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator%=(T scalar) { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> Type_<T>& operator%=(T scalar) { \
Math::Vector<size, T>::operator%=(scalar); \
return *this; \
} \
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator%(T scalar) const { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> constexpr Type_<T> operator%(T scalar) const { \
return Math::Vector<size, T>::moduloInternal(scalar, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator%=(const Math::Vector<size, T>& other) { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> Type_<T>& operator%=(const Math::Vector<size, T>& other) { \
Math::Vector<size, T>::operator%=(other); \
return *this; \
} \
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator%(const Math::Vector<size, T>& other) const { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> constexpr Type_<T> operator%(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::moduloInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
\
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator~() const { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> constexpr Type_<T> operator~() const { \
return Math::Vector<size, T>::invertInternal(typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator&=(const Math::Vector<size, T>& other) { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> Type_<T>& operator&=(const Math::Vector<size, T>& other) { \
Math::Vector<size, T>::operator&=(other); \
return *this; \
} \
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator&(const Math::Vector<size, T>& other) const { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> constexpr Type_<T> operator&(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::andInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator|=(const Math::Vector<size, T>& other) { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> Type_<T>& operator|=(const Math::Vector<size, T>& other) { \
Math::Vector<size, T>::operator|=(other); \
return *this; \
} \
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator|(const Math::Vector<size, T>& other) const { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> constexpr Type_<T> operator|(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::orInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator^=(const Math::Vector<size, T>& other) { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> Type_<T>& operator^=(const Math::Vector<size, T>& other) { \
Math::Vector<size, T>::operator^=(other); \
return *this; \
} \
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator^(const Math::Vector<size, T>& other) const { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> constexpr Type_<T> operator^(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::xorInternal(other, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator<<=(typename std::common_type<T>::type shift) { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> Type_<T>& operator<<=(typename std::common_type<T>::type shift) { \
Math::Vector<size, T>::operator<<=(shift); \
return *this; \
} \
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator<<(typename std::common_type<T>::type shift) const { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> constexpr Type_<T> operator<<(typename std::common_type<T>::type shift) const { \
return Math::Vector<size, T>::shiftLeftInternal(shift, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
template<class Integral = T> typename std::enable_if<std::is_integral<Integral>::value, Type_<T>&>::type operator>>=(typename std::common_type<T>::type shift) { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> Type_<T>& operator>>=(typename std::common_type<T>::type shift) { \
Math::Vector<size, T>::operator>>=(shift); \
return *this; \
} \
template<class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value, Type_<T>>::type operator>>(typename std::common_type<T>::type shift) const { \
template<class Integral = T, typename std::enable_if<std::is_integral<Integral>::value, int>::type = 0> constexpr Type_<T> operator>>(typename std::common_type<T>::type shift) const { \
return Math::Vector<size, T>::shiftRightInternal(shift, typename Containers::Implementation::GenerateSequence<size>::Type{}); \
} \
\
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Type_<T>>::type normalized() const { \
template<class U = T, typename std::enable_if<std::is_floating_point<U>::value, int>::type = 0> Type_<T> normalized() const { \
return Math::Vector<size, T>::normalized(); \
} \
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Type_<T>>::type resized(T length) const { \
template<class U = T, typename std::enable_if<std::is_floating_point<U>::value, int>::type = 0> Type_<T> resized(T length) const { \
return Math::Vector<size, T>::resized(length); \
} \
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Type_<T>>::type projected(const Math::Vector<size, T>& other) const { \
template<class U = T, typename std::enable_if<std::is_floating_point<U>::value, int>::type = 0> Type_<T> projected(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::projected(other); \
} \
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, Type_<T>>::type projectedOntoNormalized(const Math::Vector<size, T>& other) const { \
template<class U = T, typename std::enable_if<std::is_floating_point<U>::value, int>::type = 0> Type_<T> projectedOntoNormalized(const Math::Vector<size, T>& other) const { \
return Math::Vector<size, T>::projectedOntoNormalized(other); \
} \
constexpr Type_<T> flipped() const { \
@ -1570,12 +1526,12 @@ extern template MAGNUM_EXPORT Debug& operator<<(Debug&, const Vector<4, Double>&
VectorTest::subclass() and corresponding cases in Vector2Test, Vector3Test,
Vector4Test and ColorTest for regression tests. The same issue and a
matching workaround is done in Unit as well. */
template<std::size_t size, class FloatingPoint, class Integral> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Vector<size, Integral>>::type operator*(FloatingPoint scalar, const Vector<size, Integral>& vector) {
template<std::size_t size, class FloatingPoint, class Integral, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0> constexpr Vector<size, Integral> operator*(FloatingPoint scalar, const Vector<size, Integral>& vector) {
return vector*scalar;
}
#define MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(size, Type) \
template<class FloatingPoint, class Integral> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type<Integral>>::type operator*(FloatingPoint scalar, const Type<Integral>& vector) { \
template<class FloatingPoint, class Integral, typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, int>::type = 0> constexpr Type<Integral> operator*(FloatingPoint scalar, const Type<Integral>& vector) { \
return vector*scalar; \
}
#endif
@ -1617,12 +1573,10 @@ template<std::size_t size, class T> inline BitVector<size> Vector<size, T>::oper
}
template<std::size_t size, class T>
#ifdef DOXYGEN_GENERATING_OUTPUT
inline Vector<size, T>
#else
template<class U> inline typename std::enable_if<std::is_floating_point<U>::value, Vector<size, T>>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U, typename std::enable_if<std::is_floating_point<U>::value, int>::type>
#endif
Vector<size, T>::projectedOntoNormalized(const Vector<size, T>& line) const {
inline Vector<size, T> Vector<size, T>::projectedOntoNormalized(const Vector<size, T>& line) const {
CORRADE_DEBUG_ASSERT(line.isNormalized(),
"Math::Vector::projectedOntoNormalized(): line" << line << "is not normalized", {});
return line*Math::dot(*this, line);

16
src/Magnum/Math/Vector2.h

@ -220,12 +220,10 @@ template<class T> class Vector2: public Vector<2, T> {
* @ref Vector::operator-() const "operator-() const"
*/
/* For some reason @ref operator-() const doesn't work since 1.8.17 */
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector2<T>
#else
template<class U = T> typename std::enable_if<std::is_signed<U>::value, Vector2<T>>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U = T, typename std::enable_if<std::is_signed<U>::value, int>::type = 0>
#endif
perpendicular() const { return {-y(), x()}; }
Vector2<T> perpendicular() const { return {-y(), x()}; }
/**
* @brief Aspect ratio
@ -235,12 +233,10 @@ template<class T> class Vector2: public Vector<2, T> {
* a = \frac{v_x}{v_y}
* @f]
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
T
#else
template<class U = T> typename std::enable_if<std::is_floating_point<U>::value, T>::type
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class U = T, typename std::enable_if<std::is_floating_point<U>::value, int>::type = 0>
#endif
aspectRatio() const { return x()/y(); }
T aspectRatio() const { return x()/y(); }
MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(2, Vector2)

8
src/Magnum/MeshTools/Interleave.h

@ -50,7 +50,7 @@ namespace Implementation {
resolution (the functions would otherwise need to be de-inlined to break
cyclic dependencies) */
struct AttributeCount {
template<class T, class ...U> typename std::enable_if<!std::is_convertible<T, std::size_t>::value, std::size_t>::type operator()(const T& first, const U&...
template<class T, class ...U, typename std::enable_if<!std::is_convertible<T, std::size_t>::value, int>::type = 0> std::size_t operator()(const T& first, const U&...
#ifndef CORRADE_NO_ASSERT
next
#endif
@ -90,7 +90,7 @@ template<class T> constexpr std::size_t typeSize() {
/* Stride, taking gaps into account. It must be in the structure, same reason
as above */
struct Stride {
template<class T, class ...U> typename std::enable_if<!std::is_convertible<T, std::size_t>::value, std::size_t>::type operator()(const T&, const U&... next) const {
template<class T, class ...U, typename std::enable_if<!std::is_convertible<T, std::size_t>::value, int>::type = 0> std::size_t operator()(const T&, const U&... next) const {
return typeSize<T>() + Stride{}(next...);
}
template<class... T> std::size_t operator()(std::size_t gap, const T&... next) const {
@ -100,7 +100,7 @@ struct Stride {
};
/* Copy data to the buffer */
template<class T> typename std::enable_if<!std::is_convertible<T, std::size_t>::value, std::size_t>::type writeOneInterleaved(std::size_t stride, char* startingOffset, const T& attributeList) {
template<class T, typename std::enable_if<!std::is_convertible<T, std::size_t>::value, int>::type = 0> std::size_t writeOneInterleaved(std::size_t stride, char* startingOffset, const T& attributeList) {
auto it = attributeList.begin();
for(std::size_t i = 0; i != attributeList.size(); ++i, ++it)
std::memcpy(startingOffset + i*stride, reinterpret_cast<const char*>(&*it), typeSize<T>());
@ -150,7 +150,7 @@ would be 21 bytes, causing possible performance loss.
template<class T, class ...U
#ifndef DOXYGEN_GENERATING_OUTPUT
/* So it doesn't clash with the MeshData variant */
, class = typename std::enable_if<Utility::IsIterable<T>::value>::type
, typename std::enable_if<Utility::IsIterable<T>::value, int>::type = 0
#endif
> Containers::Array<char> interleave(const T& first, const U&... next)
{

4
src/Magnum/Platform/ScreenedApplication.h

@ -295,8 +295,8 @@ template<class Application> class BasicScreenedApplication:
CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") const BasicScreenedApplication<Application>& operator*() const { return *this; }
CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") operator BasicScreenedApplication<Application>*() { return this; }
CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") operator const BasicScreenedApplication<Application>*() const { return this; }
template<class T, class = typename std::enable_if<std::is_base_of<BasicScreenedApplication<Application>, T>::value>::type> CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") operator T*() { return static_cast<T*>(this); }
template<class T, class = typename std::enable_if<std::is_base_of<BasicScreenedApplication<Application>, T>::value>::type> CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") operator const T*() const { return static_cast<const T*>(this); }
template<class T, typename std::enable_if<std::is_base_of<BasicScreenedApplication<Application>, T>::value, int>::type = 0> CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") operator T*() { return static_cast<T*>(this); }
template<class T, typename std::enable_if<std::is_base_of<BasicScreenedApplication<Application>, T>::value, int>::type = 0> CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now") operator const T*() const { return static_cast<const T*>(this); }
CORRADE_DEPRECATED("Platform::Screen::application() returns a reference now, use hasApplication() instead") bool operator!() const { return false; }
#endif

2
src/Magnum/SceneGraph/AbstractFeature.h

@ -161,7 +161,7 @@ template<UnsignedInt dimensions, class T> class AbstractFeature
/* This is here to avoid ambiguity with deleted copy constructor when
passing `*this` from class subclassing both AbstractFeature and
AbstractObject */
template<class U, class = typename std::enable_if<std::is_base_of<AbstractObject<dimensions, T>, U>::value>::type> AbstractFeature(U& object): AbstractFeature(static_cast<AbstractObject<dimensions, T>&>(object)) {}
template<class U, typename std::enable_if<std::is_base_of<AbstractObject<dimensions, T>, U>::value, int>::type = 0> AbstractFeature(U& object): AbstractFeature(static_cast<AbstractObject<dimensions, T>&>(object)) {}
#endif
virtual ~AbstractFeature() = 0;

2
src/Magnum/SceneGraph/Animable.h

@ -139,7 +139,7 @@ template<UnsignedInt dimensions, class T> class Animable: public AbstractGrouped
#ifndef DOXYGEN_GENERATING_OUTPUT
/* This is here to avoid ambiguity with deleted copy constructor when
passing `*this` from class subclassing both Animable and AbstractObject */
template<class U, class = typename std::enable_if<std::is_base_of<AbstractObject<dimensions, T>, U>::value>::type> explicit Animable(U& object): Animable<dimensions, T>{static_cast<AbstractObject<dimensions, T>&>(object)} {}
template<class U, typename std::enable_if<std::is_base_of<AbstractObject<dimensions, T>, U>::value, int>::type = 0> explicit Animable(U& object): Animable<dimensions, T>{static_cast<AbstractObject<dimensions, T>&>(object)} {}
#endif
~Animable();

2
src/Magnum/SceneGraph/Camera.h

@ -100,7 +100,7 @@ template<UnsignedInt dimensions, class T> class Camera: public AbstractFeature<d
#ifndef DOXYGEN_GENERATING_OUTPUT
/* This is here to avoid ambiguity with deleted copy constructor when
passing `*this` from class subclassing both Camera and AbstractObject */
template<class U, class = typename std::enable_if<std::is_base_of<AbstractObject<dimensions, T>, U>::value>::type> explicit Camera(U& object): Camera<dimensions, T>{static_cast<AbstractObject<dimensions, T>&>(object)} {}
template<class U, typename std::enable_if<std::is_base_of<AbstractObject<dimensions, T>, U>::value, int>::type = 0> explicit Camera(U& object): Camera<dimensions, T>{static_cast<AbstractObject<dimensions, T>&>(object)} {}
#endif
~Camera();

2
src/Magnum/SceneGraph/Drawable.h

@ -162,7 +162,7 @@ template<UnsignedInt dimensions, class T> class Drawable: public AbstractGrouped
#ifndef DOXYGEN_GENERATING_OUTPUT
/* This is here to avoid ambiguity with deleted copy constructor when
passing `*this` from class subclassing both Drawable and AbstractObject */
template<class U, class = typename std::enable_if<std::is_base_of<AbstractObject<dimensions, T>, U>::value>::type> explicit Drawable(U& object): Drawable<dimensions, T>{static_cast<AbstractObject<dimensions, T>&>(object)} {}
template<class U, typename std::enable_if<std::is_base_of<AbstractObject<dimensions, T>, U>::value, int>::type = 0> explicit Drawable(U& object): Drawable<dimensions, T>{static_cast<AbstractObject<dimensions, T>&>(object)} {}
#endif
/**

30
src/Magnum/Trade/MaterialData.h

@ -1408,7 +1408,7 @@ class MAGNUM_TRADE_EXPORT MaterialAttributeData {
*/
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, class = typename std::enable_if<!std::is_convertible<const T&, Containers::StringView>::value && !std::is_convertible<const T&, Containers::ArrayView<const void>>::value>::type
, typename std::enable_if<!std::is_convertible<const T&, Containers::StringView>::value && !std::is_convertible<const T&, Containers::ArrayView<const void>>::value, int>::type = 0
#endif
> constexpr /*implicit*/ MaterialAttributeData(Containers::StringView name, const T& value) noexcept;
@ -1447,7 +1447,7 @@ class MAGNUM_TRADE_EXPORT MaterialAttributeData {
#ifndef DOXYGEN_GENERATING_OUTPUT
/* "Sure can't be constexpr" overloads to avoid going through the
*insane* overload puzzle when not needed */
template<class T, class = typename std::enable_if<!std::is_convertible<const T&, Containers::StringView>::value && !std::is_convertible<const T&, Containers::ArrayView<const void>>::value>::type> /*implicit*/ MaterialAttributeData(const char* name, const T& value) noexcept: MaterialAttributeData{name, Implementation::MaterialAttributeTypeFor<T>::type(), sizeof(T), &value} {}
template<class T, typename std::enable_if<!std::is_convertible<const T&, Containers::StringView>::value && !std::is_convertible<const T&, Containers::ArrayView<const void>>::value, int>::type = 0> /*implicit*/ MaterialAttributeData(const char* name, const T& value) noexcept: MaterialAttributeData{name, Implementation::MaterialAttributeTypeFor<T>::type(), sizeof(T), &value} {}
/*implicit*/ MaterialAttributeData(const char* name, Containers::StringView value) noexcept: MaterialAttributeData{name, MaterialAttributeType::String, 0, &value} {}
#endif
@ -1466,7 +1466,7 @@ class MAGNUM_TRADE_EXPORT MaterialAttributeData {
*/
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, class = typename std::enable_if<!std::is_convertible<const T&, Containers::StringView>::value>::type
, typename std::enable_if<!std::is_convertible<const T&, Containers::StringView>::value, int>::type = 0
#endif
> /*implicit*/ MaterialAttributeData(MaterialAttribute name, const T& value) noexcept: MaterialAttributeData{name, Implementation::MaterialAttributeTypeFor<T>::type(), &value} {}
@ -1677,18 +1677,18 @@ class MAGNUM_TRADE_EXPORT MaterialAttributeData {
constexpr explicit Storage(Containers::StringView name, Containers::StringView value) noexcept: s{MaterialAttributeType::String, name, value} {}
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 1, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _1{type, name, value} {}
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 4 && !std::is_pointer<T>::value, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _4{type, name, value} {}
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 8 && !Math::IsVector<T>::value && !std::is_pointer<T>::value, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _8{type, name, value} {}
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 8 && Math::IsVector<T>::value && !std::is_pointer<T>::value, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _8v{type, name, value} {}
template<class T, typename std::enable_if<sizeof(T) == 1, int>::type = 0> constexpr explicit Storage(MaterialAttributeType type, Containers::StringView name, const T& value) noexcept: _1{type, name, value} {}
template<class T, typename std::enable_if<sizeof(T) == 4 && !std::is_pointer<T>::value, int>::type = 0> constexpr explicit Storage(MaterialAttributeType type, Containers::StringView name, const T& value) noexcept: _4{type, name, value} {}
template<class T, typename std::enable_if<sizeof(T) == 8 && !Math::IsVector<T>::value && !std::is_pointer<T>::value, int>::type = 0> constexpr explicit Storage(MaterialAttributeType type, Containers::StringView name, const T& value) noexcept: _8{type, name, value} {}
template<class T, typename std::enable_if<sizeof(T) == 8 && Math::IsVector<T>::value && !std::is_pointer<T>::value, int>::type = 0> constexpr explicit Storage(MaterialAttributeType type, Containers::StringView name, const T& value) noexcept: _8v{type, name, value} {}
constexpr explicit Storage(MaterialAttributeType type, Containers::StringView name, const void* value) noexcept: p{type, name, value} {}
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 12, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _12{type, name, value} {}
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 16 && Math::IsVector<T>::value, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _16{type, name, value} {}
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 16 && !Math::IsVector<T>::value, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _16m{type, name, value} {}
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 24, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _24{type, name, value} {}
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 32, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _32{type, name, value} {}
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 36, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _36{type, name, value} {}
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 48, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _48{type, name, value} {}
template<class T, typename std::enable_if<sizeof(T) == 12, int>::type = 0> constexpr explicit Storage(MaterialAttributeType type, Containers::StringView name, const T& value) noexcept: _12{type, name, value} {}
template<class T, typename std::enable_if<sizeof(T) == 16 && Math::IsVector<T>::value, int>::type = 0> constexpr explicit Storage(MaterialAttributeType type, Containers::StringView name, const T& value) noexcept: _16{type, name, value} {}
template<class T, typename std::enable_if<sizeof(T) == 16 && !Math::IsVector<T>::value, int>::type = 0> constexpr explicit Storage(MaterialAttributeType type, Containers::StringView name, const T& value) noexcept: _16m{type, name, value} {}
template<class T, typename std::enable_if<sizeof(T) == 24, int>::type = 0> constexpr explicit Storage(MaterialAttributeType type, Containers::StringView name, const T& value) noexcept: _24{type, name, value} {}
template<class T, typename std::enable_if<sizeof(T) == 32, int>::type = 0> constexpr explicit Storage(MaterialAttributeType type, Containers::StringView name, const T& value) noexcept: _32{type, name, value} {}
template<class T, typename std::enable_if<sizeof(T) == 36, int>::type = 0> constexpr explicit Storage(MaterialAttributeType type, Containers::StringView name, const T& value) noexcept: _36{type, name, value} {}
template<class T, typename std::enable_if<sizeof(T) == 48, int>::type = 0> constexpr explicit Storage(MaterialAttributeType type, Containers::StringView name, const T& value) noexcept: _48{type, name, value} {}
MaterialAttributeType type;
char data[Implementation::MaterialAttributeDataSize];
@ -3563,7 +3563,7 @@ namespace Implementation {
/* The 2 extra bytes are for a null byte after the name and a type */
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, class
, typename std::enable_if<!std::is_convertible<const T&, Containers::StringView>::value && !std::is_convertible<const T&, Containers::ArrayView<const void>>::value, int>::type
#endif
> constexpr MaterialAttributeData::MaterialAttributeData(const Containers::StringView name, const T& value) noexcept:
_data{Implementation::MaterialAttributeTypeFor<T>::type(), (

72
src/Magnum/Trade/MeshData.h

@ -313,7 +313,7 @@ class MAGNUM_TRADE_EXPORT MeshIndexData {
* @ref MeshIndexData(std::nullptr_t) constructor.
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class T, class = typename std::enable_if<std::is_convertible<T, Containers::ArrayView<const void>>::value>::type> explicit MeshIndexData(MeshIndexType type, T&& data) noexcept;
template<class T, typename std::enable_if<std::is_convertible<T, Containers::ArrayView<const void>>::value, int>::type = 0> explicit MeshIndexData(MeshIndexType type, T&& data) noexcept;
#else
explicit MeshIndexData(MeshIndexType type, Containers::ArrayView<const void> data) noexcept;
#endif
@ -523,7 +523,7 @@ class MAGNUM_TRADE_EXPORT MeshAttributeData {
offset-only constructor (where 0 passed to offset would match with
std::nullptr_t). 0 as null pointer constant was deprecated in C++11
already, WHY IS THIS STILL A PROBLEM?! */
template<class U, class = typename std::enable_if<std::is_convertible<U, std::nullptr_t>::value && !std::is_convertible<U, std::size_t>::value>::type> explicit MeshAttributeData(MeshAttribute name, VertexFormat format, U, UnsignedShort arraySize = 0, Int morphTargetId = -1) noexcept: MeshAttributeData{nullptr, name, format, nullptr, arraySize, morphTargetId} {}
template<class U, typename std::enable_if<std::is_convertible<U, std::nullptr_t>::value && !std::is_convertible<U, std::size_t>::value, int>::type = 0> explicit MeshAttributeData(MeshAttribute name, VertexFormat format, U, UnsignedShort arraySize = 0, Int morphTargetId = -1) noexcept: MeshAttributeData{nullptr, name, format, nullptr, arraySize, morphTargetId} {}
#endif
/**
@ -1770,7 +1770,11 @@ class MAGNUM_TRADE_EXPORT MeshData {
* @ref isVertexFormatImplementationSpecific(),
* @ref attributeArraySize()
*/
template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type> Containers::StridedArrayView1D<const T> attribute(UnsignedInt id) const;
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView1D<const T> attribute(UnsignedInt id) const;
/**
* @brief Data for given array attribute in a concrete type
@ -1782,7 +1786,11 @@ class MAGNUM_TRADE_EXPORT MeshData {
* @ref attributeArraySize() for given attribute. For non-array
* attributes the second dimension has a size of @cpp 1 @ce.
*/
template<class T, class = typename std::enable_if<std::is_array<T>::value>::type> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> attribute(UnsignedInt id) const;
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> attribute(UnsignedInt id) const;
/**
* @brief Mutable data for given attribute in a concrete type
@ -1791,7 +1799,11 @@ class MAGNUM_TRADE_EXPORT MeshData {
* Expects that the mesh is mutable.
* @see @ref vertexDataFlags()
*/
template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type> Containers::StridedArrayView1D<T> mutableAttribute(UnsignedInt id);
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView1D<T> mutableAttribute(UnsignedInt id);
/**
* @brief Mutable data for given array attribute in a concrete type
@ -1803,7 +1815,11 @@ class MAGNUM_TRADE_EXPORT MeshData {
* @ref attributeArraySize() for given attribute. For non-array
* attributes the second dimension has a size of @cpp 1 @ce.
*/
template<class T, class = typename std::enable_if<std::is_array<T>::value>::type> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> mutableAttribute(UnsignedInt id);
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> mutableAttribute(UnsignedInt id);
/**
* @brief Data for given named attribute
@ -1853,7 +1869,11 @@ class MAGNUM_TRADE_EXPORT MeshData {
* @ref mutableAttribute(MeshAttribute, UnsignedInt, Int),
* @ref isVertexFormatImplementationSpecific()
*/
template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type> Containers::StridedArrayView1D<const T> attribute(MeshAttribute name, UnsignedInt id = 0, Int morphTargetId = -1) const;
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView1D<const T> attribute(MeshAttribute name, UnsignedInt id = 0, Int morphTargetId = -1) const;
/**
* @brief Data for given named array attribute in a concrete type
@ -1865,7 +1885,11 @@ class MAGNUM_TRADE_EXPORT MeshData {
* @ref attributeArraySize() for given attribute. For non-array
* attributes the second dimension has a size of @cpp 1 @ce.
*/
template<class T, class = typename std::enable_if<std::is_array<T>::value>::type> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> attribute(MeshAttribute name, UnsignedInt id = 0, Int morphTargetId = -1) const;
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> attribute(MeshAttribute name, UnsignedInt id = 0, Int morphTargetId = -1) const;
/**
* @brief Mutable data for given named attribute in a concrete type
@ -1874,7 +1898,11 @@ class MAGNUM_TRADE_EXPORT MeshData {
* returns a mutable view. Expects that the mesh is mutable.
* @see @ref vertexDataFlags()
*/
template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type> Containers::StridedArrayView1D<T> mutableAttribute(MeshAttribute name, UnsignedInt id = 0, Int morphTargetId = -1);
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView1D<T> mutableAttribute(MeshAttribute name, UnsignedInt id = 0, Int morphTargetId = -1);
/**
* @brief Mutable data for given named array attribute in a concrete type
@ -1886,7 +1914,11 @@ class MAGNUM_TRADE_EXPORT MeshData {
* @ref attributeArraySize() for given attribute. For non-array
* attributes the second dimension has a size of @cpp 1 @ce.
*/
template<class T, class = typename std::enable_if<std::is_array<T>::value>::type> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> mutableAttribute(MeshAttribute name, UnsignedInt id = 0, Int morphTargetId = -1);
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> mutableAttribute(MeshAttribute name, UnsignedInt id = 0, Int morphTargetId = -1);
/**
* @brief Indices as 32-bit integers
@ -2330,7 +2362,7 @@ namespace Implementation {
}
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class T, class> MeshIndexData::MeshIndexData(const MeshIndexType type, T&& data) noexcept: _type{type} {
template<class T, typename std::enable_if<std::is_convertible<T, Containers::ArrayView<const void>>::value, int>::type> MeshIndexData::MeshIndexData(const MeshIndexType type, T&& data) noexcept: _type{type} {
const Containers::ArrayView<const void> erased = data;
CORRADE_ASSERT(!isMeshIndexTypeImplementationSpecific(type),
"Trade::MeshIndexData: can't create index data from a contiguous view and an implementation-specific type" << Debug::hex << meshIndexTypeUnwrap(type) << Debug::nospace << ", pass a strided view instead", );
@ -2737,7 +2769,8 @@ template<class T> bool MeshData::checkVertexFormatCompatibility(const MeshAttrib
}
#endif
template<class T, class> Containers::StridedArrayView1D<const T> MeshData::attribute(const UnsignedInt id) const {
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class T, typename std::enable_if<!std::is_array<T>::value, int>::type> Containers::StridedArrayView1D<const T> MeshData::attribute(const UnsignedInt id) const {
Containers::StridedArrayView2D<const char> data = attribute(id);
#ifdef CORRADE_GRACEFUL_ASSERT /* Sigh. Brittle. Better idea? */
if(!data.stride()[1]) return {};
@ -2748,7 +2781,7 @@ template<class T, class> Containers::StridedArrayView1D<const T> MeshData::attri
return Containers::arrayCast<1, const T>(data);
}
template<class T, class> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> MeshData::attribute(const UnsignedInt id) const {
template<class T, typename std::enable_if<std::is_array<T>::value, int>::type> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> MeshData::attribute(const UnsignedInt id) const {
Containers::StridedArrayView2D<const char> data = attribute(id);
#ifdef CORRADE_GRACEFUL_ASSERT /* Sigh. Brittle. Better idea? */
if(!data.stride()[1]) return {};
@ -2759,7 +2792,7 @@ template<class T, class> Containers::StridedArrayView2D<const typename std::remo
return Containers::arrayCast<2, const typename std::remove_extent<T>::type>(data);
}
template<class T, class> Containers::StridedArrayView1D<T> MeshData::mutableAttribute(const UnsignedInt id) {
template<class T, typename std::enable_if<!std::is_array<T>::value, int>::type> Containers::StridedArrayView1D<T> MeshData::mutableAttribute(const UnsignedInt id) {
Containers::StridedArrayView2D<char> data = mutableAttribute(id);
#ifdef CORRADE_GRACEFUL_ASSERT /* Sigh. Brittle. Better idea? */
if(!data.stride()[1]) return {};
@ -2770,7 +2803,7 @@ template<class T, class> Containers::StridedArrayView1D<T> MeshData::mutableAttr
return Containers::arrayCast<1, T>(data);
}
template<class T, class> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> MeshData::mutableAttribute(const UnsignedInt id) {
template<class T, typename std::enable_if<std::is_array<T>::value, int>::type> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> MeshData::mutableAttribute(const UnsignedInt id) {
Containers::StridedArrayView2D<char> data = mutableAttribute(id);
#ifdef CORRADE_GRACEFUL_ASSERT /* Sigh. Brittle. Better idea? */
if(!data.stride()[1]) return {};
@ -2781,7 +2814,7 @@ template<class T, class> Containers::StridedArrayView2D<typename std::remove_ext
return Containers::arrayCast<2, typename std::remove_extent<T>::type>(data);
}
template<class T, class> Containers::StridedArrayView1D<const T> MeshData::attribute(const MeshAttribute name, const UnsignedInt id, const Int morphTargetId) const {
template<class T, typename std::enable_if<!std::is_array<T>::value, int>::type> Containers::StridedArrayView1D<const T> MeshData::attribute(const MeshAttribute name, const UnsignedInt id, const Int morphTargetId) const {
const UnsignedInt attributeId = findAttributeIdInternal(name, id, morphTargetId);
#ifndef CORRADE_NO_ASSERT
if(morphTargetId == -1) CORRADE_ASSERT(attributeId != ~UnsignedInt{},
@ -2798,7 +2831,7 @@ template<class T, class> Containers::StridedArrayView1D<const T> MeshData::attri
return Containers::arrayCast<1, const T>(data);
}
template<class T, class> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> MeshData::attribute(const MeshAttribute name, const UnsignedInt id, const Int morphTargetId) const {
template<class T, typename std::enable_if<std::is_array<T>::value, int>::type> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> MeshData::attribute(const MeshAttribute name, const UnsignedInt id, const Int morphTargetId) const {
const UnsignedInt attributeId = findAttributeIdInternal(name, id, morphTargetId);
#ifndef CORRADE_NO_ASSERT
if(morphTargetId == -1) CORRADE_ASSERT(attributeId != ~UnsignedInt{},
@ -2815,7 +2848,7 @@ template<class T, class> Containers::StridedArrayView2D<const typename std::remo
return Containers::arrayCast<2, const typename std::remove_extent<T>::type>(data);
}
template<class T, class> Containers::StridedArrayView1D<T> MeshData::mutableAttribute(const MeshAttribute name, const UnsignedInt id, const Int morphTargetId) {
template<class T, typename std::enable_if<!std::is_array<T>::value, int>::type> Containers::StridedArrayView1D<T> MeshData::mutableAttribute(const MeshAttribute name, const UnsignedInt id, const Int morphTargetId) {
const UnsignedInt attributeId = findAttributeIdInternal(name, id, morphTargetId);
#ifndef CORRADE_NO_ASSERT
if(morphTargetId == -1) CORRADE_ASSERT(attributeId != ~UnsignedInt{},
@ -2833,7 +2866,7 @@ template<class T, class> Containers::StridedArrayView1D<T> MeshData::mutableAttr
return Containers::arrayCast<1, T>(data);
}
template<class T, class> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> MeshData::mutableAttribute(const MeshAttribute name, const UnsignedInt id, const Int morphTargetId) {
template<class T, typename std::enable_if<std::is_array<T>::value, int>::type> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> MeshData::mutableAttribute(const MeshAttribute name, const UnsignedInt id, const Int morphTargetId) {
const UnsignedInt attributeId = findAttributeIdInternal(name, id, morphTargetId);
#ifndef CORRADE_NO_ASSERT
if(morphTargetId == -1) CORRADE_ASSERT(attributeId != ~UnsignedInt{},
@ -2850,6 +2883,7 @@ template<class T, class> Containers::StridedArrayView2D<typename std::remove_ext
#endif
return Containers::arrayCast<2, typename std::remove_extent<T>::type>(data);
}
#endif
}}

66
src/Magnum/Trade/SceneData.h

@ -2528,7 +2528,11 @@ class MAGNUM_TRADE_EXPORT SceneData {
* @see @ref field(SceneField) const, @ref mutableField(UnsignedInt),
* @ref fieldArraySize()
*/
template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type> Containers::StridedArrayView1D<const T> field(UnsignedInt id) const;
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView1D<const T> field(UnsignedInt id) const;
/**
* @brief Data for given array field in a concrete type
@ -2541,7 +2545,11 @@ class MAGNUM_TRADE_EXPORT SceneData {
* @ref fieldArraySize(UnsignedInt) const for given field. For
* non-array fields the second dimension has a size of @cpp 1 @ce.
*/
template<class T, class = typename std::enable_if<std::is_array<T>::value>::type> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> field(UnsignedInt id) const;
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> field(UnsignedInt id) const;
/**
* @brief Mutable data for given field in a concrete type
@ -2551,7 +2559,11 @@ class MAGNUM_TRADE_EXPORT SceneData {
* Expects that the scene is mutable.
* @see @ref dataFlags()
*/
template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type> Containers::StridedArrayView1D<T> mutableField(UnsignedInt id);
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView1D<T> mutableField(UnsignedInt id);
/**
* @brief Mutable data for given array field in a concrete type
@ -2564,7 +2576,11 @@ class MAGNUM_TRADE_EXPORT SceneData {
* @ref fieldArraySize(UnsignedInt) const for given field. For
* non-array fields the second dimension has a size of @cpp 1 @ce.
*/
template<class T, class = typename std::enable_if<std::is_array<T>::value>::type> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> mutableField(UnsignedInt id);
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> mutableField(UnsignedInt id);
/**
* @brief Data for given named field
@ -2608,7 +2624,11 @@ class MAGNUM_TRADE_EXPORT SceneData {
* @see @ref hasField(), @ref field(UnsignedInt) const,
* @ref mutableField(SceneField)
*/
template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type> Containers::StridedArrayView1D<const T> field(SceneField name) const;
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView1D<const T> field(SceneField name) const;
/**
* @brief Data for given named array field in a concrete type
@ -2621,7 +2641,11 @@ class MAGNUM_TRADE_EXPORT SceneData {
* @ref fieldArraySize(SceneField) const for given field. For non-array
* fields the second dimension has a size of @cpp 1 @ce.
*/
template<class T, class = typename std::enable_if<std::is_array<T>::value>::type> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> field(SceneField name) const;
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> field(SceneField name) const;
/**
* @brief Mutable data for given named field
@ -2631,7 +2655,11 @@ class MAGNUM_TRADE_EXPORT SceneData {
* Expects that the scene is mutable.
* @see @ref dataFlags()
*/
template<class T, class = typename std::enable_if<!std::is_array<T>::value>::type> Containers::StridedArrayView1D<T> mutableField(SceneField name);
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<!std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView1D<T> mutableField(SceneField name);
/**
* @brief Mutable data for given named array field in a concrete type
@ -2644,7 +2672,11 @@ class MAGNUM_TRADE_EXPORT SceneData {
* @ref fieldArraySize(SceneField) const for given field. For non-array
* fields the second dimension has a size of @cpp 1 @ce.
*/
template<class T, class = typename std::enable_if<std::is_array<T>::value>::type> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> mutableField(SceneField name);
template<class T
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<std::is_array<T>::value, int>::type = 0
#endif
> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> mutableField(SceneField name);
/**
* @brief Contents of given bit field
@ -4265,7 +4297,8 @@ template<class T> bool SceneData::checkFieldTypeCompatibility(const SceneFieldDa
}
#endif
template<class T, class> Containers::StridedArrayView1D<const T> SceneData::field(const UnsignedInt id) const {
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class T, typename std::enable_if<!std::is_array<T>::value, int>::type> Containers::StridedArrayView1D<const T> SceneData::field(const UnsignedInt id) const {
Containers::StridedArrayView2D<const char> data = field(id);
#ifdef CORRADE_GRACEFUL_ASSERT /* Sigh. Brittle. Better idea? */
if(!data.stride()[1]) return {};
@ -4276,7 +4309,7 @@ template<class T, class> Containers::StridedArrayView1D<const T> SceneData::fiel
return Containers::arrayCast<1, const T>(data);
}
template<class T, class> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> SceneData::field(const UnsignedInt id) const {
template<class T, typename std::enable_if<std::is_array<T>::value, int>::type> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> SceneData::field(const UnsignedInt id) const {
Containers::StridedArrayView2D<const char> data = field(id);
#ifdef CORRADE_GRACEFUL_ASSERT /* Sigh. Brittle. Better idea? */
if(!data.stride()[1]) return {};
@ -4287,7 +4320,7 @@ template<class T, class> Containers::StridedArrayView2D<const typename std::remo
return Containers::arrayCast<2, const typename std::remove_extent<T>::type>(data);
}
template<class T, class> Containers::StridedArrayView1D<T> SceneData::mutableField(const UnsignedInt id) {
template<class T, typename std::enable_if<!std::is_array<T>::value, int>::type> Containers::StridedArrayView1D<T> SceneData::mutableField(const UnsignedInt id) {
Containers::StridedArrayView2D<char> data = mutableField(id);
#ifdef CORRADE_GRACEFUL_ASSERT /* Sigh. Brittle. Better idea? */
if(!data.stride()[1]) return {};
@ -4298,7 +4331,7 @@ template<class T, class> Containers::StridedArrayView1D<T> SceneData::mutableFie
return Containers::arrayCast<1, T>(data);
}
template<class T, class> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> SceneData::mutableField(const UnsignedInt id) {
template<class T, typename std::enable_if<std::is_array<T>::value, int>::type> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> SceneData::mutableField(const UnsignedInt id) {
Containers::StridedArrayView2D<char> data = mutableField(id);
#ifdef CORRADE_GRACEFUL_ASSERT /* Sigh. Brittle. Better idea? */
if(!data.stride()[1]) return {};
@ -4309,7 +4342,7 @@ template<class T, class> Containers::StridedArrayView2D<typename std::remove_ext
return Containers::arrayCast<2, typename std::remove_extent<T>::type>(data);
}
template<class T, class> Containers::StridedArrayView1D<const T> SceneData::field(const SceneField name) const {
template<class T, typename std::enable_if<!std::is_array<T>::value, int>::type> Containers::StridedArrayView1D<const T> SceneData::field(const SceneField name) const {
const UnsignedInt fieldId = findFieldIdInternal(name);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::field(): field" << name << "not found", {});
@ -4323,7 +4356,7 @@ template<class T, class> Containers::StridedArrayView1D<const T> SceneData::fiel
return Containers::arrayCast<1, const T>(data);
}
template<class T, class> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> SceneData::field(const SceneField name) const {
template<class T, typename std::enable_if<std::is_array<T>::value, int>::type> Containers::StridedArrayView2D<const typename std::remove_extent<T>::type> SceneData::field(const SceneField name) const {
const UnsignedInt fieldId = findFieldIdInternal(name);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::field(): field" << name << "not found", {});
@ -4337,7 +4370,7 @@ template<class T, class> Containers::StridedArrayView2D<const typename std::remo
return Containers::arrayCast<2, const typename std::remove_extent<T>::type>(data);
}
template<class T, class> Containers::StridedArrayView1D<T> SceneData::mutableField(const SceneField name) {
template<class T, typename std::enable_if<!std::is_array<T>::value, int>::type> Containers::StridedArrayView1D<T> SceneData::mutableField(const SceneField name) {
const UnsignedInt fieldId = findFieldIdInternal(name);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::mutableField(): field" << name << "not found", {});
@ -4351,7 +4384,7 @@ template<class T, class> Containers::StridedArrayView1D<T> SceneData::mutableFie
return Containers::arrayCast<1, T>(data);
}
template<class T, class> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> SceneData::mutableField(const SceneField name) {
template<class T, typename std::enable_if<std::is_array<T>::value, int>::type> Containers::StridedArrayView2D<typename std::remove_extent<T>::type> SceneData::mutableField(const SceneField name) {
const UnsignedInt fieldId = findFieldIdInternal(name);
CORRADE_ASSERT(fieldId != ~UnsignedInt{},
"Trade::SceneData::mutableField(): field" << name << "not found", {});
@ -4364,6 +4397,7 @@ template<class T, class> Containers::StridedArrayView2D<typename std::remove_ext
#endif
return Containers::arrayCast<2, typename std::remove_extent<T>::type>(data);
}
#endif
}}

12
src/Magnum/Vk/Extensions.h

@ -214,7 +214,11 @@ class MAGNUM_VK_EXPORT InstanceExtension {
constexpr Containers::StringView string() const { return _string; }
/** @brief Construct from a compile-time instance extension */
template<class E, class = typename std::enable_if<Implementation::IsInstanceExtension<E>::value>::type> constexpr /*implicit*/ InstanceExtension(const E&): _index{E::InstanceIndex}, _requiredVersion{E::requiredVersion()}, _coreVersion{E::coreVersion()}, _string{E::string()} {}
template<class E
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<Implementation::IsInstanceExtension<E>::value, int>::type = 0
#endif
> constexpr /*implicit*/ InstanceExtension(const E&): _index{E::InstanceIndex}, _requiredVersion{E::requiredVersion()}, _coreVersion{E::coreVersion()}, _string{E::string()} {}
private:
std::size_t _index;
@ -253,7 +257,11 @@ class MAGNUM_VK_EXPORT Extension {
/** @brief Construct from a compile-time device extension */
/** @todo prohibit conversion from GL/AL extensions also? */
template<class E, class = typename std::enable_if<Implementation::IsExtension<E>::value>::type> constexpr /*implicit*/ Extension(const E&): _index{E::Index}, _requiredVersion{E::requiredVersion()}, _coreVersion{E::coreVersion()}, _string{E::string()} {}
template<class E
#ifndef DOXYGEN_GENERATING_OUTPUT
, typename std::enable_if<Implementation::IsExtension<E>::value, int>::type = 0
#endif
> constexpr /*implicit*/ Extension(const E&): _index{E::Index}, _requiredVersion{E::requiredVersion()}, _coreVersion{E::coreVersion()}, _string{E::string()} {}
private:
std::size_t _index;

2
src/Magnum/Vk/Implementation/structureHelpers.h

@ -101,7 +101,7 @@ template<class T> inline const void** structureFind(const void*& next, const T&
class AnyStructure {
public:
template<class T, class = typename std::enable_if<IsVulkanStructure<T>::value>::type> /*implicit*/ AnyStructure(const T& structure): _structure{reinterpret_cast<const VkBaseOutStructure*>(&structure)} {}
template<class T, typename std::enable_if<IsVulkanStructure<T>::value, int>::type = 0> /*implicit*/ AnyStructure(const T& structure): _structure{reinterpret_cast<const VkBaseOutStructure*>(&structure)} {}
/*implicit*/ operator const VkBaseOutStructure&() const { return *_structure; }

Loading…
Cancel
Save