Cleanup: add utility macro to simplify using std::enable_if

This commit is contained in:
Jacques Lucke 2022-01-10 12:28:23 +01:00
parent 934db6a820
commit bd8fa07a3d
6 changed files with 28 additions and 19 deletions

View File

@ -209,7 +209,7 @@ class Any {
/**
* Constructs a new #Any that contains the given value.
*/
template<typename T, typename X = std::enable_if_t<!is_same_any_v<T>, void>>
template<typename T, BLI_ENABLE_IF((!is_same_any_v<T>))>
Any(T &&value) : Any(std::in_place_type<T>, std::forward<T>(value))
{
}

View File

@ -100,7 +100,7 @@ class Array {
/**
* Create a new array that contains copies of all values.
*/
template<typename U, typename std::enable_if_t<std::is_convertible_v<U, T>> * = nullptr>
template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))>
Array(Span<U> values, Allocator allocator = {}) : Array(NoExceptConstructor(), allocator)
{
const int64_t size = values.size();
@ -112,7 +112,7 @@ class Array {
/**
* Create a new array that contains copies of all values.
*/
template<typename U, typename std::enable_if_t<std::is_convertible_v<U, T>> * = nullptr>
template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))>
Array(const std::initializer_list<U> &values, Allocator allocator = {})
: Array(Span<U>(values), allocator)
{
@ -230,13 +230,13 @@ class Array {
return MutableSpan<T>(data_, size_);
}
template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<T, U>> * = nullptr>
template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<T, U>))>
operator Span<U>() const
{
return Span<U>(data_, size_);
}
template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<T, U>> * = nullptr>
template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<T, U>))>
operator MutableSpan<U>()
{
return MutableSpan<U>(data_, size_);

View File

@ -80,6 +80,8 @@
*
*/
#include "BLI_memory_utils.hh"
namespace blender {
template<typename Function> class FunctionRef;
@ -125,8 +127,8 @@ template<typename Ret, typename... Params> class FunctionRef<Ret(Params...)> {
* another lambda.
*/
template<typename Callable,
std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Callable>>,
FunctionRef>> * = nullptr>
BLI_ENABLE_IF((
!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Callable>>, FunctionRef>))>
FunctionRef(Callable &&callable)
: callback_(callback_fn<typename std::remove_reference_t<Callable>>),
callable_(reinterpret_cast<intptr_t>(&callable))

View File

@ -557,4 +557,13 @@ Container &move_assign_container(Container &dst, Container &&src) noexcept(
return dst;
}
/**
* Utility macro that wraps `std::enable_if` to make it a bit easier to use and less verbose for
* SFINAE in common cases.
*
* \note Often one has to invoke this macro with double parenthesis. That's because the condition
* often contains a comma and angle brackets are not recognized as parenthesis by the preprocessor.
*/
#define BLI_ENABLE_IF(condition) typename std::enable_if_t<condition> * = nullptr
} // namespace blender

View File

@ -109,7 +109,7 @@ template<typename T> class Span {
BLI_assert(size >= 0);
}
template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<U, T>> * = nullptr>
template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<U, T>))>
constexpr Span(const U *start, int64_t size) : data_(static_cast<const T *>(start)), size_(size)
{
BLI_assert(size >= 0);
@ -144,7 +144,7 @@ template<typename T> class Span {
* Support implicit conversions like the one below:
* Span<T *> -> Span<const T *>
*/
template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<U, T>> * = nullptr>
template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<U, T>))>
constexpr Span(Span<U> span) : data_(static_cast<const T *>(span.data())), size_(span.size())
{
}
@ -501,7 +501,7 @@ template<typename T> class MutableSpan {
* Support implicit conversions like the one below:
* MutableSpan<T *> -> MutableSpan<const T *>
*/
template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<U, T>> * = nullptr>
template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<U, T>))>
constexpr MutableSpan(MutableSpan<U> span)
: data_(static_cast<T *>(span.data())), size_(span.size())
{
@ -512,7 +512,7 @@ template<typename T> class MutableSpan {
return Span<T>(data_, size_);
}
template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<T, U>> * = nullptr>
template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<T, U>))>
constexpr operator Span<U>() const
{
return Span<U>(static_cast<const U *>(data_), size_);

View File

@ -163,7 +163,7 @@ class Vector {
/**
* Create a vector from a span. The values in the vector are copy constructed.
*/
template<typename U, typename std::enable_if_t<std::is_convertible_v<U, T>> * = nullptr>
template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))>
Vector(Span<U> values, Allocator allocator = {}) : Vector(NoExceptConstructor(), allocator)
{
const int64_t size = values.size();
@ -178,7 +178,7 @@ class Vector {
* This allows you to write code like:
* Vector<int> vec = {3, 4, 5};
*/
template<typename U, typename std::enable_if_t<std::is_convertible_v<U, T>> * = nullptr>
template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))>
Vector(const std::initializer_list<U> &values) : Vector(Span<U>(values))
{
}
@ -187,9 +187,7 @@ class Vector {
{
}
template<typename U,
size_t N,
typename std::enable_if_t<std::is_convertible_v<U, T>> * = nullptr>
template<typename U, size_t N, BLI_ENABLE_IF((std::is_convertible_v<U, T>))>
Vector(const std::array<U, N> &values) : Vector(Span(values))
{
}
@ -197,7 +195,7 @@ class Vector {
template<typename InputIt,
/* This constructor should not be called with e.g. Vector(3, 10), because that is
* expected to produce the vector (10, 10, 10). */
typename std::enable_if_t<!std::is_convertible_v<InputIt, int>> * = nullptr>
BLI_ENABLE_IF((!std::is_convertible_v<InputIt, int>))>
Vector(InputIt first, InputIt last, Allocator allocator = {})
: Vector(NoExceptConstructor(), allocator)
{
@ -326,13 +324,13 @@ class Vector {
return MutableSpan<T>(begin_, this->size());
}
template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<T, U>> * = nullptr>
template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<T, U>))>
operator Span<U>() const
{
return Span<U>(begin_, this->size());
}
template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<T, U>> * = nullptr>
template<typename U, BLI_ENABLE_IF((is_span_convertible_pointer_v<T, U>))>
operator MutableSpan<U>()
{
return MutableSpan<U>(begin_, this->size());