Skip to content

Commit

Permalink
Removed redundant typename in SFINAE expressions.
Browse files Browse the repository at this point in the history
  • Loading branch information
crisluengo committed Jun 24, 2024
1 parent d6b2fc7 commit 3da6e67
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 43 deletions.
22 changes: 11 additions & 11 deletions include/diplib/library/clamp_cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,12 @@ struct NeedsLowerClamping {
);
};

template< typename ValueType, typename LimitType, typename std::enable_if_t< NeedsLowerClamping< ValueType, LimitType >::value, int > = 0 >
template< typename ValueType, typename LimitType, std::enable_if_t< NeedsLowerClamping< ValueType, LimitType >::value, int > = 0 >
constexpr inline ValueType clamp_lower( ValueType value, LimitType limit ) {
// `value` is a float or a signed integer with more digits than limit. Casting `limit` to the type of `value` is not a problem.
return std::max( value, static_cast< ValueType >( limit ));
}
template< typename ValueType, typename LimitType, typename std::enable_if_t< !NeedsLowerClamping< ValueType, LimitType >::value, int > = 0 >
template< typename ValueType, typename LimitType, std::enable_if_t< !NeedsLowerClamping< ValueType, LimitType >::value, int > = 0 >
constexpr inline ValueType clamp_lower( ValueType value, LimitType /*limit*/ ) {
// `value` is a signed integer with same or fewer digits than `limit`
return value;
Expand All @@ -193,11 +193,11 @@ struct NeedsUpperClamping {
|| ( detail::numeric_limits< ValueType >::digits > detail::numeric_limits< LimitType >::digits );
};

template< typename ValueType, typename LimitType, typename std::enable_if_t< NeedsUpperClamping< ValueType, LimitType >::value, int > = 0 >
template< typename ValueType, typename LimitType, std::enable_if_t< NeedsUpperClamping< ValueType, LimitType >::value, int > = 0 >
constexpr inline ValueType clamp_upper( ValueType value, LimitType limit ) {
return std::min( value, static_cast< ValueType >( limit ));
}
template< typename ValueType, typename LimitType, typename std::enable_if_t< !NeedsUpperClamping< ValueType, LimitType >::value, int > = 0 >
template< typename ValueType, typename LimitType, std::enable_if_t< !NeedsUpperClamping< ValueType, LimitType >::value, int > = 0 >
constexpr inline ValueType clamp_upper( ValueType value, LimitType /*limit*/ ) {
return value;
}
Expand All @@ -208,21 +208,21 @@ constexpr inline ValueType clamp_upper( ValueType value, LimitType /*limit*/ ) {
/// \ingroup pixeltypes
// Cast non-complex value to float
template< typename TargetType, typename SourceType,
typename std::enable_if_t< detail::is_floating_point< TargetType >::value, int > = 0 >
std::enable_if_t< detail::is_floating_point< TargetType >::value, int > = 0 >
constexpr inline TargetType clamp_cast( SourceType v ) {
return static_cast< TargetType >( v );
}

// Cast non-complex value to complex
template< typename TargetType, typename SourceType,
typename std::enable_if_t< detail::is_complex< TargetType >::value, int > = 0 >
std::enable_if_t< detail::is_complex< TargetType >::value, int > = 0 >
constexpr inline TargetType clamp_cast( SourceType v ) {
return static_cast< TargetType >( static_cast< typename TargetType::value_type >( v ));
}

// Cast non-complex value to integer
template< typename TargetType, typename SourceType,
typename std::enable_if_t< detail::is_integer< TargetType >::value, int > = 0 >
std::enable_if_t< detail::is_integer< TargetType >::value, int > = 0 >
constexpr inline TargetType clamp_cast( SourceType v ) {
static_assert( detail::numeric_limits< TargetType >::is_specialized, "It looks like detail::numeric_limits is not specialized for the target type." );
static_assert( detail::numeric_limits< SourceType >::is_specialized, "It looks like detail::numeric_limits is not specialized for the source type." );
Expand All @@ -236,28 +236,28 @@ constexpr inline TargetType clamp_cast( SourceType v ) {

// Cast non-complex value to bin
template< typename TargetType, typename SourceType,
typename std::enable_if_t< detail::is_binary< TargetType >::value, int > = 0 >
std::enable_if_t< detail::is_binary< TargetType >::value, int > = 0 >
constexpr inline TargetType clamp_cast( SourceType v ) {
return static_cast< TargetType >( v ); // The logic is built into the `dip::bin` class
}

// Cast bin value to anything (except to complex, that's handled below)
template< typename TargetType,
typename std::enable_if_t< !detail::is_complex< TargetType >::value, int > = 0 >
std::enable_if_t< !detail::is_complex< TargetType >::value, int > = 0 >
constexpr inline TargetType clamp_cast( dip::bin v ) {
return static_cast< TargetType >( v );
}

// Casting from complex to non-complex, we take the absolute value and cast as if from a float
template< typename TargetType, typename SourceType,
typename std::enable_if_t< !detail::is_complex< TargetType >::value, int > = 0 >
std::enable_if_t< !detail::is_complex< TargetType >::value, int > = 0 >
constexpr inline TargetType clamp_cast( std::complex< SourceType > v ) {
return clamp_cast< TargetType >( std::abs( v ));
}

// Casting from complex to complex
template< typename TargetType, typename SourceType,
typename std::enable_if_t< detail::is_complex< TargetType >::value, int > = 0 >
std::enable_if_t< detail::is_complex< TargetType >::value, int > = 0 >
constexpr inline TargetType clamp_cast( std::complex< SourceType > v ) {
return { static_cast< typename TargetType::value_type >( v.real() ), static_cast< typename TargetType::value_type >( v.imag() ) };
}
Expand Down
2 changes: 1 addition & 1 deletion include/diplib/library/image_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ class Image::Pixel {

/// \brief A `Pixel` can be constructed from an initializer list, yielding a pixel with the same data
/// type and number of tensor elements as the initializer list. The pixel will be a column vector.
template< typename T, typename std::enable_if_t< IsNumericType< T >::value, int > = 0 >
template< typename T, std::enable_if_t< IsNumericType< T >::value, int > = 0 >
Pixel( std::initializer_list< T > values ) { // NOLINT(*-pro-type-member-init)
dip::uint N = values.size();
tensor_.SetVector( N );
Expand Down
8 changes: 4 additions & 4 deletions include/diplib/library/numeric.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ constexpr inline dip::uint gcd( dip::uint a, dip::uint b ) {
}

/// \brief Integer division, unsigned, return ceil.
template< typename T, typename std::enable_if_t< std::is_integral< T >::value && !std::is_signed< T >::value, int > = 0 >
template< typename T, std::enable_if_t< std::is_integral< T >::value && !std::is_signed< T >::value, int > = 0 >
constexpr T div_ceil( T lhs, T rhs ) {
if(( lhs == 0 ) || ( rhs == 0 )) {
return 0;
Expand All @@ -90,7 +90,7 @@ constexpr T div_ceil( T lhs, T rhs ) {
}

/// \brief Integer division, signed, return ceil. If signs differ, adding or subtracting one from `lhs` should not overflow.
template< typename T, typename std::enable_if_t< std::is_integral< T >::value && std::is_signed< T >::value, int > = 0 >
template< typename T, std::enable_if_t< std::is_integral< T >::value && std::is_signed< T >::value, int > = 0 >
constexpr T div_ceil( T lhs, T rhs ) {
if(( lhs == 0 ) || ( rhs == 0 )) {
return 0;
Expand All @@ -105,7 +105,7 @@ constexpr T div_ceil( T lhs, T rhs ) {
}

/// \brief Integer division, unsigned, return floor.
template< typename T, typename std::enable_if_t< std::is_integral< T >::value && !std::is_signed< T >::value, int > = 0 >
template< typename T, std::enable_if_t< std::is_integral< T >::value && !std::is_signed< T >::value, int > = 0 >
constexpr T div_floor( T lhs, T rhs ) {
if(( lhs == 0 ) || ( rhs == 0 )) {
return 0;
Expand All @@ -114,7 +114,7 @@ constexpr T div_floor( T lhs, T rhs ) {
}

/// \brief Integer division, signed, return floor. If signs differ, adding or subtracting one from `lhs` should not overflow.
template< typename T, typename std::enable_if_t< std::is_integral< T >::value && std::is_signed< T >::value, int > = 0 >
template< typename T, std::enable_if_t< std::is_integral< T >::value && std::is_signed< T >::value, int > = 0 >
constexpr T div_floor( T lhs, T rhs ) {
if(( lhs == 0 ) || ( rhs == 0 )) {
return 0;
Expand Down
4 changes: 2 additions & 2 deletions include/diplib/library/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@ template<> struct IsIndexingType< dip::sint > { static constexpr bool value = tr
/// you'll need to use the following form:
///
/// ```cpp
/// template< typename T, typename std::enable_if_t< dip::IsSampleType< T >::value, int > = 0 >
/// template< typename T, std::enable_if_t< dip::IsSampleType< T >::value, int > = 0 >
/// void MyFunction( T value ) { ... }
/// template< typename T, typename std::enable_if_t< !dip::IsSampleType< T >::value, int > = 0 >
/// template< typename T, std::enable_if_t< !dip::IsSampleType< T >::value, int > = 0 >
/// void MyFunction( T value ) { ... }
/// ```
template< typename T > struct IsSampleType : public detail::IsSampleType< std::remove_cv_t< std::remove_reference_t< T >>> {};
Expand Down
38 changes: 19 additions & 19 deletions include/diplib/saturated_arithmetic.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,22 @@ template<> struct LargerType< sint64 > { using type = __int128_t; };

/// \brief Adds two values using saturated arithmetic.
// Floats and complex don't overflow
template< typename T, typename std::enable_if_t< detail::is_floating_point< T >::value
|| detail::is_complex< T >::value, int > = 0 >
template< typename T, std::enable_if_t< detail::is_floating_point< T >::value
|| detail::is_complex< T >::value, int > = 0 >
constexpr inline T saturated_add( T lhs, T rhs ) {
return lhs + rhs;
}

// Unsigned integers overflow by giving a result that is smaller than either operand.
// This code is supposed to be branchless, the compiler optimizes using a conditional move.
template< typename T, typename std::enable_if_t< detail::is_unsigned_integer< T >::value, int > = 0 >
template< typename T, std::enable_if_t< detail::is_unsigned_integer< T >::value, int > = 0 >
constexpr inline T saturated_add( T lhs, T rhs ) {
T res = static_cast< T >( lhs + rhs ); // There's an implicit conversion to unsigned/int for smaller types
return res < lhs ? std::numeric_limits< T >::max() : res;
}

// Signed integers are more complex, we simply use a larger integer type to do the operation.
template< typename T, typename std::enable_if_t< detail::is_signed_integer< T >::value, int > = 0 >
template< typename T, std::enable_if_t< detail::is_signed_integer< T >::value, int > = 0 >
constexpr inline T saturated_add( T lhs, T rhs ) {
return clamp_cast< T >( static_cast< typename detail::LargerType< T >::type >( lhs )
+ static_cast< typename detail::LargerType< T >::type >( rhs ));
Expand Down Expand Up @@ -115,22 +115,22 @@ constexpr inline bin saturated_add( bin lhs, bin rhs ) {

/// \brief Subtracts two values using saturated arithmetic.
// Floats and complex don't overflow
template< typename T, typename std::enable_if_t< detail::is_floating_point< T >::value
|| detail::is_complex< T >::value, int > = 0 >
template< typename T, std::enable_if_t< detail::is_floating_point< T >::value
|| detail::is_complex< T >::value, int > = 0 >
constexpr inline T saturated_sub( T lhs, T rhs ) {
return lhs - rhs;
}

// Unsigned integers underflow by giving a result that is larger than either operand.
// This code is supposed to be branchless, the compiler optimizes using a conditional move.
template< typename T, typename std::enable_if_t< detail::is_unsigned_integer< T >::value, int > = 0 >
template< typename T, std::enable_if_t< detail::is_unsigned_integer< T >::value, int > = 0 >
constexpr inline T saturated_sub( T lhs, T rhs ) {
T res = static_cast< T >( lhs - rhs ); // There's an implicit conversion to unsigned/int for smaller types
return res > lhs ? T( 0 ) : res;
}

// Signed integers are more complex, we simply use a larger integer type to do the operation.
template< typename T, typename std::enable_if_t< detail::is_signed_integer< T >::value, int > = 0 >
template< typename T, std::enable_if_t< detail::is_signed_integer< T >::value, int > = 0 >
constexpr inline T saturated_sub( T lhs, T rhs ) {
return clamp_cast< T >( static_cast< typename detail::LargerType< T >::type >( lhs )
- static_cast< typename detail::LargerType< T >::type >( rhs ));
Expand Down Expand Up @@ -160,14 +160,14 @@ constexpr inline bin saturated_sub( bin lhs, bin rhs ) {

/// \brief Multiplies two values using saturated arithmetic.
// Floats and complex don't overflow
template< typename T, typename std::enable_if_t< detail::is_floating_point< T >::value
|| detail::is_complex< T >::value, int > = 0 >
template< typename T, std::enable_if_t< detail::is_floating_point< T >::value
|| detail::is_complex< T >::value, int > = 0 >
constexpr inline T saturated_mul( T lhs, T rhs ) {
return lhs * rhs;
}

// For signed and unsigned integers we simply use a larger integer type to do the operation.
template< typename T, typename std::enable_if_t< detail::is_integer< T >::value, int > = 0 >
template< typename T, std::enable_if_t< detail::is_integer< T >::value, int > = 0 >
constexpr inline T saturated_mul( T lhs, T rhs ) {
return clamp_cast< T >( static_cast< typename detail::LargerType< T >::type >( lhs )
* static_cast< typename detail::LargerType< T >::type >( rhs ));
Expand Down Expand Up @@ -203,15 +203,15 @@ constexpr inline bin saturated_mul( bin lhs, bin rhs ) {

/// \brief Divides two values using saturated arithmetic.
// Floats, complex and unsigned integers don't overflow
template< typename T, typename std::enable_if_t< detail::is_floating_point< T >::value
|| detail::is_complex< T >::value
|| detail::is_unsigned_integer< T >::value, int > = 0 >
template< typename T, std::enable_if_t< detail::is_floating_point< T >::value
|| detail::is_complex< T >::value
|| detail::is_unsigned_integer< T >::value, int > = 0 >
constexpr inline T saturated_div( T lhs, T rhs ) {
return static_cast< T >( lhs / rhs ); // There's an implicit conversion to unsigned/int for smaller types
}

// Signed integer division can overflow if we divide INT_MIN by -1
template< typename T, typename std::enable_if_t< detail::is_signed_integer< T >::value, int > = 0 >
template< typename T, std::enable_if_t< detail::is_signed_integer< T >::value, int > = 0 >
constexpr inline T saturated_div( T lhs, T rhs ) {
return (( lhs == std::numeric_limits< T >::lowest()) && ( rhs == -1 ))
? std::numeric_limits< T >::max() : static_cast< T >( lhs / rhs ); // There's an implicit conversion to unsigned/int for smaller types
Expand Down Expand Up @@ -241,20 +241,20 @@ constexpr inline bin saturated_safediv( bin lhs, bin rhs ) {

/// \brief Inverts a value using saturated arithmetic. This is the same as negation, but not for unsigned values.
// Floats and complex are straight-forward
template< typename T, typename std::enable_if_t< detail::is_floating_point< T >::value
|| detail::is_complex< T >::value, int > = 0 >
template< typename T, std::enable_if_t< detail::is_floating_point< T >::value
|| detail::is_complex< T >::value, int > = 0 >
constexpr inline T saturated_inv( T v ) {
return -v;
}

// Unsigned integers invert by subtracting from max value.
template< typename T, typename std::enable_if_t< detail::is_unsigned_integer< T >::value, int > = 0 >
template< typename T, std::enable_if_t< detail::is_unsigned_integer< T >::value, int > = 0 >
constexpr inline T saturated_inv( T v ) {
return static_cast< T >( std::numeric_limits< T >::max() - v ); // There's an implicit conversion to unsigned/int for smaller types
}

// Signed integers seem simple but overflow can happen if the value is equal to lowest possible value
template< typename T, typename std::enable_if_t< detail::is_signed_integer< T >::value, int > = 0 >
template< typename T, std::enable_if_t< detail::is_signed_integer< T >::value, int > = 0 >
constexpr inline T saturated_inv( T v ) {
return v == std::numeric_limits< T >::lowest() ? std::numeric_limits< T >::max() : static_cast< T >( -v ); // There's an implicit conversion to unsigned/int for smaller types
}
Expand Down
4 changes: 2 additions & 2 deletions include/diplib/testing.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ namespace testing {
namespace detail {

// For integral types -- dip::sint can hold the value of any integer-valued pixel.
template< typename T, typename std::enable_if_t< std::is_integral< T >::value, int > = 0 >
template< typename T, std::enable_if_t< std::is_integral< T >::value, int > = 0 >
dip::sint Round( T v, int /*digits*/ ) {
return v;
}
Expand All @@ -71,7 +71,7 @@ inline dip::sint Round( bin v, int /*digits*/ ) {
}

// For floating-point types
template< typename T, typename std::enable_if_t< !std::is_integral< T >::value, int > = 0 >
template< typename T, std::enable_if_t< !std::is_integral< T >::value, int > = 0 >
T Round( T v, int digits ) {
if( !std::isfinite( v )) {
return v;
Expand Down
4 changes: 2 additions & 2 deletions src/library/pixel_table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ void PixelTable::AsImage( Image& out ) const {

namespace {

template< typename TPI, typename std::enable_if_t< !(std::is_same< TPI, scomplex >::value || std::is_same< TPI, dcomplex >::value), int > = 0 >
template< typename TPI, std::enable_if_t< !(std::is_same< TPI, scomplex >::value || std::is_same< TPI, dcomplex >::value), int > = 0 >
void AddWeightsInternal(
Image const& image,
dip::sint stride,
Expand All @@ -459,7 +459,7 @@ void AddWeightsInternal(
}
}

template< typename TPI, typename std::enable_if_t< std::is_same< TPI, scomplex >::value || std::is_same< TPI, dcomplex >::value, int > = 0 >
template< typename TPI, std::enable_if_t< std::is_same< TPI, scomplex >::value || std::is_same< TPI, dcomplex >::value, int > = 0 >
void AddWeightsInternal(
Image const& image,
dip::sint stride,
Expand Down
4 changes: 2 additions & 2 deletions src/morphology/areaopening.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ For the volume opening, we do the same thing but track the volume of the peak in
*/

// Add value and changed, but if TPI is an integer type, round change towards zero first.
template< typename TPI, typename std::enable_if_t< std::numeric_limits< TPI >::is_integer, int > = 0 >
template< typename TPI, std::enable_if_t< std::numeric_limits< TPI >::is_integer, int > = 0 >
TPI AddSigned( TPI value, dfloat change ) {
return clamp_cast< TPI >( static_cast< dip::sint >( value ) + static_cast< dip::sint >( std::trunc( change )));
// Note we'd get some overflow here if TPI is a dip::uint64 and the value doesn't fit in a dip::sint64. Oh. well.
}
template< typename TPI, typename std::enable_if_t< !std::numeric_limits< TPI >::is_integer, int > = 0 >
template< typename TPI, std::enable_if_t< !std::numeric_limits< TPI >::is_integer, int > = 0 >
TPI AddSigned( TPI value, dfloat change ) {
return clamp_cast< TPI >( static_cast< dfloat >( value ) + change );
}
Expand Down

0 comments on commit 3da6e67

Please sign in to comment.