diff --git a/cpp/src/arrow/acero/asof_join_node.cc b/cpp/src/arrow/acero/asof_join_node.cc index 3970050e5022..7af8358da94e 100644 --- a/cpp/src/arrow/acero/asof_join_node.cc +++ b/cpp/src/arrow/acero/asof_join_node.cc @@ -130,7 +130,8 @@ typedef uint64_t row_index_t; typedef int col_index_t; // indicates normalization of a key value -template ::value, bool> = true> +template + requires std::is_integral_v static inline uint64_t key_value(T t) { return static_cast(t); } diff --git a/cpp/src/arrow/acero/time_series_util.cc b/cpp/src/arrow/acero/time_series_util.cc index 60f9044d7bf7..655569285cf5 100644 --- a/cpp/src/arrow/acero/time_series_util.cc +++ b/cpp/src/arrow/acero/time_series_util.cc @@ -22,7 +22,8 @@ namespace arrow::acero { -template ::value, bool>> +template + requires std::is_integral_v inline uint64_t NormalizeTime(T t) { uint64_t bias = std::is_signed::value ? static_cast(1) << (8 * sizeof(T) - 1) : 0; diff --git a/cpp/src/arrow/acero/time_series_util.h b/cpp/src/arrow/acero/time_series_util.h index 97707f43bf20..697a810bf90b 100644 --- a/cpp/src/arrow/acero/time_series_util.h +++ b/cpp/src/arrow/acero/time_series_util.h @@ -23,7 +23,8 @@ namespace arrow::acero { // normalize the value to unsigned 64-bits while preserving ordering of values -template ::value, bool> = true> +template + requires std::is_integral_v uint64_t NormalizeTime(T t); uint64_t GetTime(const RecordBatch* batch, Type::type time_type, int col, uint64_t row); diff --git a/cpp/src/arrow/acero/unmaterialized_table_internal.h b/cpp/src/arrow/acero/unmaterialized_table_internal.h index 86b1a763a603..f636f7ba681e 100644 --- a/cpp/src/arrow/acero/unmaterialized_table_internal.h +++ b/cpp/src/arrow/acero/unmaterialized_table_internal.h @@ -166,8 +166,9 @@ class UnmaterializedCompositeTable { } template ::BuilderType> - enable_if_boolean static BuilderAppend( - Builder& builder, const std::shared_ptr& source, uint64_t row) { + requires arrow_boolean + static Status BuilderAppend(Builder& builder, const std::shared_ptr& source, + uint64_t row) { if (source->IsNull(row)) { builder.UnsafeAppendNull(); return Status::OK(); @@ -177,10 +178,9 @@ class UnmaterializedCompositeTable { } template ::BuilderType> - enable_if_t::value && !is_boolean_type::value, - Status> static BuilderAppend(Builder& builder, - const std::shared_ptr& source, - uint64_t row) { + requires(arrow_fixed_width && !arrow_boolean) + static Status BuilderAppend(Builder& builder, const std::shared_ptr& source, + uint64_t row) { if (source->IsNull(row)) { builder.UnsafeAppendNull(); return Status::OK(); @@ -191,8 +191,9 @@ class UnmaterializedCompositeTable { } template ::BuilderType> - enable_if_base_binary static BuilderAppend( - Builder& builder, const std::shared_ptr& source, uint64_t row) { + requires arrow_base_binary + static Status BuilderAppend(Builder& builder, const std::shared_ptr& source, + uint64_t row) { if (source->IsNull(row)) { return builder.AppendNull(); } diff --git a/cpp/src/arrow/adapters/orc/util.cc b/cpp/src/arrow/adapters/orc/util.cc index 6974faae59b5..cf0358b8e961 100644 --- a/cpp/src/arrow/adapters/orc/util.cc +++ b/cpp/src/arrow/adapters/orc/util.cc @@ -488,21 +488,17 @@ Result> NormalizeArray(const std::shared_ptr& arra } } -template +template struct Appender {}; // Types for long/double-like Appender, that is, numeric, boolean or date32 template -using is_generic_type = - std::integral_constant::value || - std::is_same::value || - is_boolean_type::value>; -template -using enable_if_generic = enable_if_t::value, R>; +concept generic_type = arrow_number || std::same_as || arrow_boolean; // Number-like template -struct Appender> { + requires generic_type +struct Appender { using ArrayType = typename TypeTraits::ArrayType; using ValueType = typename TypeTraits::CType; Status VisitNull() { diff --git a/cpp/src/arrow/array/array_dict.cc b/cpp/src/arrow/array/array_dict.cc index 2e54e6ec4904..6d7c8a98df94 100644 --- a/cpp/src/arrow/array/array_dict.cc +++ b/cpp/src/arrow/array/array_dict.cc @@ -289,7 +289,8 @@ struct CompactTransposeMapVisitor { } template - enable_if_integer Visit(const Type&) { + requires arrow_integer + Status Visit(const Type&) { return CompactTransposeMapImpl(); } @@ -435,14 +436,16 @@ struct MakeUnifier { : pool(pool), value_type(std::move(value_type)) {} template - enable_if_no_memoize Visit(const T&) { + requires dictionary_has_no_memo_table + Status Visit(const T&) { // Default implementation for non-dictionary-supported datatypes return Status::NotImplemented("Unification of ", *value_type, " dictionaries is not implemented"); } template - enable_if_memoize Visit(const T&) { + requires dictionary_has_memo_table + Status Visit(const T&) { result.reset(new DictionaryUnifierImpl(pool, value_type)); return Status::OK(); } diff --git a/cpp/src/arrow/array/array_list_test.cc b/cpp/src/arrow/array/array_list_test.cc index 8406bd1d8ed1..9d3a27a05d77 100644 --- a/cpp/src/arrow/array/array_list_test.cc +++ b/cpp/src/arrow/array/array_list_test.cc @@ -330,7 +330,8 @@ class TestListArray : public ::testing::Test { } template - std::enable_if_t TestFromArraysWithSlicedOffsets() { + requires IsList + void TestFromArraysWithSlicedOffsets() { std::vector offsets = {-1, -1, 0, 1, 2, 4}; std::shared_ptr offsets_wo_nulls; @@ -356,7 +357,8 @@ class TestListArray : public ::testing::Test { } template - std::enable_if_t TestFromArraysWithSlicedNullOffsets() { + requires IsList + void TestFromArraysWithSlicedNullOffsets() { std::vector offsets = {-1, -1, 0, 1, 1, 3}; std::vector offsets_w_nulls_is_valid = {true, true, true, false, true, true}; @@ -479,7 +481,8 @@ class TestListArray : public ::testing::Test { } template - std::enable_if_t DoTestListViewFromArrays() { + requires IsListView + void DoTestListViewFromArrays() { std::shared_ptr offsets1, offsets2; std::shared_ptr sizes1, sizes2, sizes3, sizes4, sizes5; std::shared_ptr values; diff --git a/cpp/src/arrow/array/array_primitive.h b/cpp/src/arrow/array/array_primitive.h index cebf47ad93d8..d582bfcd5d3c 100644 --- a/cpp/src/arrow/array/array_primitive.h +++ b/cpp/src/arrow/array/array_primitive.h @@ -97,8 +97,8 @@ class NumericArray : public PrimitiveArray { // Only enable this constructor without a type argument for types without additional // metadata template - NumericArray(enable_if_parameter_free length, - const std::shared_ptr& data, + requires arrow_parameter_free + NumericArray(int64_t length, const std::shared_ptr& data, const std::shared_ptr& null_bitmap = NULLPTR, int64_t null_count = kUnknownNullCount, int64_t offset = 0) { NumericArray::SetData(ArrayData::Make(TypeTraits::type_singleton(), length, diff --git a/cpp/src/arrow/array/array_test.cc b/cpp/src/arrow/array/array_test.cc index 64ea3fd71a73..8f55405d8d94 100644 --- a/cpp/src/arrow/array/array_test.cc +++ b/cpp/src/arrow/array/array_test.cc @@ -1328,7 +1328,8 @@ class TestPrimitiveBuilder : public TestBuilder { /// \brief uint8_t isn't a valid template parameter to uniform_int_distribution, so /// we use SampleType to determine which kind of integer to use to sample. -template ::value, T>> +template + requires std::is_integral_v struct UniformIntSampleType { using type = T; }; diff --git a/cpp/src/arrow/array/builder_adaptive.cc b/cpp/src/arrow/array/builder_adaptive.cc index 3cd5a46321f4..703a10ac49dc 100644 --- a/cpp/src/arrow/array/builder_adaptive.cc +++ b/cpp/src/arrow/array/builder_adaptive.cc @@ -64,14 +64,14 @@ Status AdaptiveIntBuilderBase::Resize(int64_t capacity) { } template -typename std::enable_if= sizeof(new_type), Status>::type -AdaptiveIntBuilderBase::ExpandIntSizeInternal() { + requires(sizeof(old_type) >= sizeof(new_type)) +Status AdaptiveIntBuilderBase::ExpandIntSizeInternal() { return Status::OK(); } template -typename std::enable_if<(sizeof(old_type) < sizeof(new_type)), Status>::type -AdaptiveIntBuilderBase::ExpandIntSizeInternal() { + requires(sizeof(old_type) < sizeof(new_type)) +Status AdaptiveIntBuilderBase::ExpandIntSizeInternal() { int_size_ = sizeof(new_type); RETURN_NOT_OK(Resize(data_->size() / sizeof(old_type))); diff --git a/cpp/src/arrow/array/builder_adaptive.h b/cpp/src/arrow/array/builder_adaptive.h index 0cea571be3e3..1da225ceac4b 100644 --- a/cpp/src/arrow/array/builder_adaptive.h +++ b/cpp/src/arrow/array/builder_adaptive.h @@ -113,11 +113,11 @@ class ARROW_EXPORT AdaptiveIntBuilderBase : public ArrayBuilder { virtual Status CommitPendingData() = 0; template - typename std::enable_if= sizeof(new_type), Status>::type - ExpandIntSizeInternal(); + requires(sizeof(old_type) >= sizeof(new_type)) + Status ExpandIntSizeInternal(); template - typename std::enable_if<(sizeof(old_type) < sizeof(new_type)), Status>::type - ExpandIntSizeInternal(); + requires(sizeof(old_type) < sizeof(new_type)) + Status ExpandIntSizeInternal(); std::shared_ptr data_; uint8_t* raw_data_ = NULLPTR; diff --git a/cpp/src/arrow/array/builder_base.cc b/cpp/src/arrow/array/builder_base.cc index 03deacdb01de..7a569d148c64 100644 --- a/cpp/src/arrow/array/builder_base.cc +++ b/cpp/src/arrow/array/builder_base.cc @@ -114,7 +114,8 @@ struct AppendScalarImpl { } template - enable_if_t::value, Status> Visit(const T& t) { + requires arrow_has_c_type + Status Visit(const T& t) { return HandleFixedWidth(t); } @@ -125,7 +126,8 @@ struct AppendScalarImpl { Status Visit(const Decimal256Type& t) { return HandleFixedWidth(t); } template - enable_if_has_string_view Visit(const T&) { + requires arrow_has_string_view + Status Visit(const T&) { int64_t data_size = 0; for (auto it = scalars_begin_; it != scalars_end_; ++it) { const auto& scalar = checked_cast::ScalarType&>(*it); @@ -152,8 +154,8 @@ struct AppendScalarImpl { } template - enable_if_t::value || is_list_like_type::value, Status> Visit( - const T&) { + requires(arrow_list_view || arrow_list_like) + Status Visit(const T&) { auto builder = checked_cast::BuilderType*>(builder_); int64_t num_children = 0; for (auto it = scalars_begin_; it != scalars_end_; ++it) { diff --git a/cpp/src/arrow/array/builder_dict.cc b/cpp/src/arrow/array/builder_dict.cc index c3b4ceb1a6d3..09819aa81b2b 100644 --- a/cpp/src/arrow/array/builder_dict.cc +++ b/cpp/src/arrow/array/builder_dict.cc @@ -44,13 +44,15 @@ class DictionaryMemoTable::DictionaryMemoTableImpl { std::unique_ptr* memo_table_; template - enable_if_no_memoize Visit(const T&) { + requires dictionary_has_no_memo_table + Status Visit(const T&) { return Status::NotImplemented("Initialization of ", value_type_->ToString(), " memo table is not implemented"); } template - enable_if_memoize Visit(const T&) { + requires dictionary_has_memo_table + Status Visit(const T&) { using MemoTable = typename DictionaryTraits::MemoTableType; memo_table_->reset(new MemoTable(pool_, 0)); return Status::OK(); @@ -70,13 +72,15 @@ class DictionaryMemoTable::DictionaryMemoTableImpl { private: template - enable_if_no_memoize InsertValues(const T& type, const ArrayType&) { + requires dictionary_has_no_memo_table + Status InsertValues(const T& type, const ArrayType&) { return Status::NotImplemented("Inserting array values of ", type, " is not implemented"); } template - enable_if_memoize InsertValues(const T&, const ArrayType& array) { + requires dictionary_has_memo_table + Status InsertValues(const T&, const ArrayType& array) { if (array.null_count() > 0) { return Status::Invalid("Cannot insert dictionary values containing nulls"); } @@ -97,13 +101,15 @@ class DictionaryMemoTable::DictionaryMemoTableImpl { std::shared_ptr* out_; template - enable_if_no_memoize Visit(const T&) { + requires dictionary_has_no_memo_table + Status Visit(const T&) { return Status::NotImplemented("Getting array data of ", value_type_, " is not implemented"); } template - enable_if_memoize Visit(const T&) { + requires dictionary_has_memo_table + Status Visit(const T&) { using ConcreteMemoTable = typename DictionaryTraits::MemoTableType; auto memo_table = checked_cast(memo_table_); ARROW_ASSIGN_OR_RAISE(*out_, DictionaryTraits::GetDictionaryArrayData( diff --git a/cpp/src/arrow/array/builder_dict.h b/cpp/src/arrow/array/builder_dict.h index 116c82049eea..b5ad6837b32b 100644 --- a/cpp/src/arrow/array/builder_dict.h +++ b/cpp/src/arrow/array/builder_dict.h @@ -46,28 +46,28 @@ namespace arrow { namespace internal { -template +template struct DictionaryValue { using type = typename T::c_type; using PhysicalType = T; }; -template -struct DictionaryValue> { +template +struct DictionaryValue { using type = std::string_view; using PhysicalType = typename std::conditional::value, BinaryType, LargeBinaryType>::type; }; -template -struct DictionaryValue> { +template +struct DictionaryValue { using type = std::string_view; using PhysicalType = BinaryViewType; }; -template -struct DictionaryValue> { +template +struct DictionaryValue { using type = std::string_view; using PhysicalType = BinaryType; }; @@ -148,11 +148,9 @@ class DictionaryBuilderBase : public ArrayBuilder { // WARNING: the type given below is the value type, not the DictionaryType. // The DictionaryType is instantiated on the Finish() call. template + requires(std::is_base_of_v && !arrow_fixed_size_binary) DictionaryBuilderBase(uint8_t start_int_size, - enable_if_t::value && - !is_fixed_size_binary_type::value, - const std::shared_ptr&> - value_type, + const std::shared_ptr& value_type, MemoryPool* pool = default_memory_pool(), int64_t alignment = kDefaultBufferAlignment) : ArrayBuilder(pool, alignment), @@ -163,11 +161,10 @@ class DictionaryBuilderBase : public ArrayBuilder { value_type_(value_type) {} template - explicit DictionaryBuilderBase( - enable_if_t::value, const std::shared_ptr&> - value_type, - MemoryPool* pool = default_memory_pool(), - int64_t alignment = kDefaultBufferAlignment) + requires(!arrow_fixed_size_binary) + explicit DictionaryBuilderBase(const std::shared_ptr& value_type, + MemoryPool* pool = default_memory_pool(), + int64_t alignment = kDefaultBufferAlignment) : ArrayBuilder(pool, alignment), memo_table_(new internal::DictionaryMemoTable(pool, value_type)), delta_offset_(0), @@ -176,12 +173,11 @@ class DictionaryBuilderBase : public ArrayBuilder { value_type_(value_type) {} template - explicit DictionaryBuilderBase( - const std::shared_ptr& index_type, - enable_if_t::value, const std::shared_ptr&> - value_type, - MemoryPool* pool = default_memory_pool(), - int64_t alignment = kDefaultBufferAlignment) + requires(!arrow_fixed_size_binary) + explicit DictionaryBuilderBase(const std::shared_ptr& index_type, + const std::shared_ptr& value_type, + MemoryPool* pool = default_memory_pool(), + int64_t alignment = kDefaultBufferAlignment) : ArrayBuilder(pool, alignment), memo_table_(new internal::DictionaryMemoTable(pool, value_type)), delta_offset_(0), @@ -190,11 +186,9 @@ class DictionaryBuilderBase : public ArrayBuilder { value_type_(value_type) {} template + requires(std::is_base_of_v && arrow_fixed_size_binary) DictionaryBuilderBase(uint8_t start_int_size, - enable_if_t::value && - is_fixed_size_binary_type::value, - const std::shared_ptr&> - value_type, + const std::shared_ptr& value_type, MemoryPool* pool = default_memory_pool(), int64_t alignment = kDefaultBufferAlignment) : ArrayBuilder(pool, alignment), @@ -205,10 +199,10 @@ class DictionaryBuilderBase : public ArrayBuilder { value_type_(value_type) {} template - explicit DictionaryBuilderBase( - enable_if_fixed_size_binary&> value_type, - MemoryPool* pool = default_memory_pool(), - int64_t alignment = kDefaultBufferAlignment) + requires arrow_fixed_size_binary + explicit DictionaryBuilderBase(const std::shared_ptr& value_type, + MemoryPool* pool = default_memory_pool(), + int64_t alignment = kDefaultBufferAlignment) : ArrayBuilder(pool, alignment), memo_table_(new internal::DictionaryMemoTable(pool, value_type)), delta_offset_(0), @@ -217,11 +211,11 @@ class DictionaryBuilderBase : public ArrayBuilder { value_type_(value_type) {} template - explicit DictionaryBuilderBase( - const std::shared_ptr& index_type, - enable_if_fixed_size_binary&> value_type, - MemoryPool* pool = default_memory_pool(), - int64_t alignment = kDefaultBufferAlignment) + requires arrow_fixed_size_binary + explicit DictionaryBuilderBase(const std::shared_ptr& index_type, + const std::shared_ptr& value_type, + MemoryPool* pool = default_memory_pool(), + int64_t alignment = kDefaultBufferAlignment) : ArrayBuilder(pool, alignment), memo_table_(new internal::DictionaryMemoTable(pool, value_type)), delta_offset_(0), @@ -230,8 +224,8 @@ class DictionaryBuilderBase : public ArrayBuilder { value_type_(value_type) {} template - explicit DictionaryBuilderBase( - enable_if_parameter_free pool = default_memory_pool()) + requires arrow_parameter_free + explicit DictionaryBuilderBase(MemoryPool* pool = default_memory_pool()) : DictionaryBuilderBase(TypeTraits::type_singleton(), pool) {} // This constructor doesn't check for errors. Use InsertMemoValues instead. @@ -252,7 +246,8 @@ class DictionaryBuilderBase : public ArrayBuilder { /// \brief The value byte width (for FixedSizeBinaryType) template - enable_if_fixed_size_binary byte_width() const { + requires arrow_fixed_size_binary + int32_t byte_width() const { return byte_width_; } @@ -270,37 +265,43 @@ class DictionaryBuilderBase : public ArrayBuilder { /// \brief Append a fixed-width string (only for FixedSizeBinaryType) template - enable_if_fixed_size_binary Append(const uint8_t* value) { + requires arrow_fixed_size_binary + Status Append(const uint8_t* value) { return Append(std::string_view(reinterpret_cast(value), byte_width_)); } /// \brief Append a fixed-width string (only for FixedSizeBinaryType) template - enable_if_fixed_size_binary Append(const char* value) { + requires arrow_fixed_size_binary + Status Append(const char* value) { return Append(std::string_view(value, byte_width_)); } /// \brief Append a string (only for binary types) template - enable_if_binary_like Append(const uint8_t* value, int32_t length) { + requires arrow_binary_like + Status Append(const uint8_t* value, int32_t length) { return Append(reinterpret_cast(value), length); } /// \brief Append a string (only for binary types) template - enable_if_binary_like Append(const char* value, int32_t length) { + requires arrow_binary_like + Status Append(const char* value, int32_t length) { return Append(std::string_view(value, length)); } /// \brief Append a string (only for string types) template - enable_if_string_like Append(const char* value, int32_t length) { + requires arrow_string_like + Status Append(const char* value, int32_t length) { return Append(std::string_view(value, length)); } /// \brief Append a decimal (only for Decimal32/64/128/256 Type) template ::CType> - enable_if_decimal Append(const CType& value) { + requires arrow_decimal + Status Append(const CType& value) { auto bytes = value.ToBytes(); return Append(bytes.data(), static_cast(bytes.size())); } @@ -411,8 +412,8 @@ class DictionaryBuilderBase : public ArrayBuilder { /// \brief Append a whole dense array to the builder template - enable_if_t::value, Status> AppendArray( - const Array& array) { + requires(!arrow_fixed_size_binary) + Status AppendArray(const Array& array) { using ArrayType = typename TypeTraits::ArrayType; #ifndef NDEBUG @@ -432,7 +433,8 @@ class DictionaryBuilderBase : public ArrayBuilder { } template - enable_if_fixed_size_binary AppendArray(const Array& array) { + requires arrow_fixed_size_binary + Status AppendArray(const Array& array) { #ifndef NDEBUG ARROW_RETURN_NOT_OK(ArrayBuilder::CheckArrayType( value_type_, array, "Wrong value type of array to be appended")); @@ -567,11 +569,10 @@ template class DictionaryBuilderBase : public ArrayBuilder { public: template - DictionaryBuilderBase( - enable_if_t::value, uint8_t> - start_int_size, - const std::shared_ptr& value_type, - MemoryPool* pool = default_memory_pool()) + requires std::is_base_of_v + DictionaryBuilderBase(uint8_t start_int_size, + const std::shared_ptr& value_type, + MemoryPool* pool = default_memory_pool()) : ArrayBuilder(pool), indices_builder_(start_int_size, pool) {} explicit DictionaryBuilderBase(const std::shared_ptr& value_type, @@ -584,10 +585,9 @@ class DictionaryBuilderBase : public ArrayBuilder { : ArrayBuilder(pool), indices_builder_(index_type, pool) {} template - explicit DictionaryBuilderBase( - enable_if_t::value, uint8_t> - start_int_size, - MemoryPool* pool = default_memory_pool()) + requires std::is_base_of_v + explicit DictionaryBuilderBase(uint8_t start_int_size, + MemoryPool* pool = default_memory_pool()) : ArrayBuilder(pool), indices_builder_(start_int_size, pool) {} explicit DictionaryBuilderBase(MemoryPool* pool = default_memory_pool()) diff --git a/cpp/src/arrow/array/builder_primitive.h b/cpp/src/arrow/array/builder_primitive.h index 6d79d6e96499..205bf3cbbf87 100644 --- a/cpp/src/arrow/array/builder_primitive.h +++ b/cpp/src/arrow/array/builder_primitive.h @@ -19,6 +19,7 @@ #include #include +#include #include #include "arrow/array/builder_base.h" @@ -88,9 +89,9 @@ class NumericBuilder using ArrayType = typename TypeTraits::ArrayType; template - explicit NumericBuilder( - enable_if_parameter_free pool = default_memory_pool(), - int64_t alignment = kDefaultBufferAlignment) + requires arrow_parameter_free + explicit NumericBuilder(MemoryPool* pool = default_memory_pool(), + int64_t alignment = kDefaultBufferAlignment) : ArrayBuilder(pool, alignment), type_(TypeTraits::type_singleton()), data_builder_(pool, alignment) {} @@ -268,8 +269,9 @@ class NumericBuilder /// or null(0) values. /// \return Status template - enable_if_t::value, Status> AppendValues( - ValuesIter values_begin, ValuesIter values_end, ValidIter valid_begin) { + requires(!std::is_pointer_v) + Status AppendValues(ValuesIter values_begin, ValuesIter values_end, + ValidIter valid_begin) { static_assert(!internal::is_null_pointer::value, "Don't pass a NULLPTR directly as valid_begin, use the 2-argument " "version instead"); @@ -285,8 +287,9 @@ class NumericBuilder // Same as above, with a pointer type ValidIter template - enable_if_t::value, Status> AppendValues( - ValuesIter values_begin, ValuesIter values_end, ValidIter valid_begin) { + requires std::is_pointer_v + Status AppendValues(ValuesIter values_begin, ValuesIter values_end, + ValidIter valid_begin) { int64_t length = static_cast(std::distance(values_begin, values_end)); ARROW_RETURN_NOT_OK(Reserve(length)); data_builder_.UnsafeAppend(values_begin, values_end); @@ -624,8 +627,9 @@ class ARROW_EXPORT BooleanBuilder /// or null(0) values /// \return Status template - enable_if_t::value, Status> AppendValues( - ValuesIter values_begin, ValuesIter values_end, ValidIter valid_begin) { + requires(!std::is_pointer_v) + Status AppendValues(ValuesIter values_begin, ValuesIter values_end, + ValidIter valid_begin) { static_assert(!internal::is_null_pointer::value, "Don't pass a NULLPTR directly as valid_begin, use the 2-argument " "version instead"); @@ -643,8 +647,9 @@ class ARROW_EXPORT BooleanBuilder // Same as above, for a pointer type ValidIter template - enable_if_t::value, Status> AppendValues( - ValuesIter values_begin, ValuesIter values_end, ValidIter valid_begin) { + requires std::is_pointer_v + Status AppendValues(ValuesIter values_begin, ValuesIter values_end, + ValidIter valid_begin) { int64_t length = static_cast(std::distance(values_begin, values_end)); ARROW_RETURN_NOT_OK(Reserve(length)); data_builder_.UnsafeAppend( diff --git a/cpp/src/arrow/array/concatenate.cc b/cpp/src/arrow/array/concatenate.cc index 2b832b977f23..b4dd4d1ddc66 100644 --- a/cpp/src/arrow/array/concatenate.cc +++ b/cpp/src/arrow/array/concatenate.cc @@ -500,7 +500,8 @@ class ConcatenateImpl { } template - enable_if_list_view Visit(const T& type) { + requires arrow_list_view + Status Visit(const T& type) { using offset_type = typename T::offset_type; out_->buffers.resize(3); out_->child_data.resize(1); diff --git a/cpp/src/arrow/array/dict_internal.h b/cpp/src/arrow/array/dict_internal.h index 8ddc4b448a7e..784a0c6b0cf5 100644 --- a/cpp/src/arrow/array/dict_internal.h +++ b/cpp/src/arrow/array/dict_internal.h @@ -19,6 +19,7 @@ #include "arrow/array/builder_dict.h" +#include #include #include #include @@ -40,22 +41,27 @@ namespace arrow { namespace internal { -template +template struct DictionaryTraits { using MemoTableType = void; }; } // namespace internal +template +concept dictionary_has_memo_table = + !std::same_as::MemoTableType, void>; + +template +concept dictionary_has_no_memo_table = + std::same_as::MemoTableType, void>; + +// Keep compatibility aliases while downstream files are migrated. template -using enable_if_memoize = enable_if_t< - !std::is_same::MemoTableType, void>::value, - Out>; +using enable_if_memoize = enable_if_t, Out>; template -using enable_if_no_memoize = enable_if_t< - std::is_same::MemoTableType, void>::value, - Out>; +using enable_if_no_memoize = enable_if_t, Out>; namespace internal { @@ -87,8 +93,8 @@ struct DictionaryTraits { } }; // namespace internal -template -struct DictionaryTraits> { +template +struct DictionaryTraits { using c_type = typename T::c_type; using MemoTableType = typename HashTraits::MemoTableType; @@ -115,8 +121,8 @@ struct DictionaryTraits> { } }; -template -struct DictionaryTraits> { +template +struct DictionaryTraits { using MemoTableType = typename HashTraits::MemoTableType; static Result> GetDictionaryArrayData( @@ -150,8 +156,8 @@ struct DictionaryTraits> { } }; -template -struct DictionaryTraits> { +template +struct DictionaryTraits { using MemoTableType = typename HashTraits::MemoTableType; static_assert(std::is_same_v>); @@ -176,8 +182,8 @@ struct DictionaryTraits> { } }; -template -struct DictionaryTraits> { +template +struct DictionaryTraits { using MemoTableType = typename HashTraits::MemoTableType; static Result> GetDictionaryArrayData( diff --git a/cpp/src/arrow/array/diff.cc b/cpp/src/arrow/array/diff.cc index fd907e3c7b29..6706e7aa239b 100644 --- a/cpp/src/arrow/array/diff.cc +++ b/cpp/src/arrow/array/diff.cc @@ -76,8 +76,8 @@ struct Slice { bool operator!=(const Slice& other) const { return !(*this == other); } }; -template > +template + requires arrow_list_like static Slice GetView(const ArrayType& array, int64_t index) { return Slice{array.values().get(), array.value_offset(index), array.value_length(index)}; @@ -614,7 +614,8 @@ class MakeFormatterImpl { // format Numerics with std::ostream defaults template - enable_if_number Visit(const T&) { + requires arrow_number + Status Visit(const T&) { impl_ = [](const Array& array, int64_t index, std::ostream* os) { const auto& numeric = checked_cast&>(array); if (sizeof(decltype(numeric.Value(index))) == sizeof(char)) { @@ -629,7 +630,8 @@ class MakeFormatterImpl { } template - enable_if_date Visit(const T&) { + requires arrow_date + Status Visit(const T&) { using unit = typename std::conditional::value, arrow_vendored::date::days, std::chrono::milliseconds>::type; @@ -644,7 +646,8 @@ class MakeFormatterImpl { } template - enable_if_time Visit(const T&) { + requires arrow_time + Status Visit(const T&) { impl_ = MakeTimeFormatter("%T"); return Status::OK(); } @@ -673,7 +676,8 @@ class MakeFormatterImpl { } template - enable_if_has_string_view Visit(const T&) { + requires arrow_has_string_view + Status Visit(const T&) { using ArrayType = typename TypeTraits::ArrayType; impl_ = [](const Array& array, int64_t index, std::ostream* os) { std::string_view view = checked_cast(array).GetView(index); @@ -690,7 +694,8 @@ class MakeFormatterImpl { // format Decimals with Decimal___Array::FormatValue template - enable_if_decimal Visit(const T&) { + requires arrow_decimal + Status Visit(const T&) { impl_ = [](const Array& array, int64_t index, std::ostream* os) { const auto& decimal_array = checked_cast::ArrayType&>(array); @@ -700,7 +705,8 @@ class MakeFormatterImpl { } template - enable_if_list_like Visit(const T& t) { + requires arrow_list_like + Status Visit(const T& t) { struct ListImpl { explicit ListImpl(Formatter f) : values_formatter_(std::move(f)) {} diff --git a/cpp/src/arrow/array/util.cc b/cpp/src/arrow/array/util.cc index 03d8c32c4e36..764d43a1ab78 100644 --- a/cpp/src/arrow/array/util.cc +++ b/cpp/src/arrow/array/util.cc @@ -141,11 +141,8 @@ class ArrayDataEndianSwapper { } template - enable_if_t::value && - !std::is_base_of::value && - !std::is_base_of::value, - Status> - Visit(const T& type) { + requires(arrow_fixed_width && !arrow_fixed_size_binary && !arrow_dictionary) + Status Visit(const T& type) { using value_type = typename T::c_type; ARROW_ASSIGN_OR_RAISE(out_->buffers[1], ByteSwapBuffer(data_->buffers[1])); @@ -153,7 +150,8 @@ class ArrayDataEndianSwapper { } template - enable_if_decimal Visit(const T& type) { + requires arrow_decimal + Status Visit(const T& type) { using value_type = typename TypeTraits::CType; auto data = data_->buffers[1]->span_as(); ARROW_ASSIGN_OR_RAISE(auto new_buffer, @@ -219,19 +217,16 @@ class ArrayDataEndianSwapper { } template - enable_if_t::value || std::is_same::value, - Status> - Visit(const T& type) { + requires(std::is_same_v || std::is_same_v) + Status Visit(const T& type) { RETURN_NOT_OK(SwapOffsets(1)); out_->buffers[2] = data_->buffers[2]; return Status::OK(); } template - enable_if_t::value || - std::is_same::value, - Status> - Visit(const T& type) { + requires(std::is_same_v || std::is_same_v) + Status Visit(const T& type) { RETURN_NOT_OK(SwapOffsets(1)); out_->buffers[2] = data_->buffers[2]; return Status::OK(); @@ -350,7 +345,8 @@ class NullArrayFactory { } template - enable_if_var_size_list Visit(const T& type) { + requires arrow_var_length_list + Status Visit(const T& type) { // values array may be empty, but there must be at least one offset of 0 RETURN_NOT_OK(MaxOf(sizeof(typename T::offset_type) * (length_ + 1))); RETURN_NOT_OK(MaxOf(GetBufferLength(type.value_type(), /*length=*/0))); @@ -358,14 +354,16 @@ class NullArrayFactory { } template - enable_if_list_view Visit(const T& type) { + requires arrow_list_view + Status Visit(const T& type) { RETURN_NOT_OK(MaxOf(sizeof(typename T::offset_type) * length_)); RETURN_NOT_OK(MaxOf(GetBufferLength(type.value_type(), /*length=*/0))); return Status::OK(); } template - enable_if_base_binary Visit(const T&) { + requires arrow_base_binary + Status Visit(const T&) { // values buffer may be empty, but there must be at least one offset of 0 return MaxOf(sizeof(typename T::offset_type) * (length_ + 1)); } @@ -488,7 +486,8 @@ class NullArrayFactory { } template - enable_if_base_binary Visit(const T&) { + requires arrow_base_binary + Status Visit(const T&) { out_->buffers.resize(3, buffer_); return Status::OK(); } @@ -499,7 +498,8 @@ class NullArrayFactory { } template - enable_if_var_length_list_like Visit(const T& type) { + requires arrow_var_length_list_like + Status Visit(const T& type) { out_->buffers.resize(is_list_view(T::type_id) ? 3 : 2, buffer_); ARROW_ASSIGN_OR_RAISE(out_->child_data[0], CreateChild(type, 0, /*length=*/0)); return Status::OK(); @@ -624,8 +624,8 @@ class RepeatedArrayFactory { } template - enable_if_t::value || is_temporal_type::value, Status> Visit( - const T&) { + requires(arrow_number || arrow_temporal) + Status Visit(const T&) { auto value = scalar().value; return FinishFixedWidth(&value, sizeof(value)); } @@ -636,7 +636,8 @@ class RepeatedArrayFactory { } template - enable_if_decimal Visit(const T&) { + requires arrow_decimal + Status Visit(const T&) { auto value = scalar().value.ToBytes(); return FinishFixedWidth(value.data(), value.size()); } @@ -647,7 +648,8 @@ class RepeatedArrayFactory { } template - enable_if_base_binary Visit(const T&) { + requires arrow_base_binary + Status Visit(const T&) { const std::shared_ptr& value = scalar().value; std::shared_ptr values_buffer, offsets_buffer; RETURN_NOT_OK(CreateBufferOf(value->data(), value->size(), &values_buffer)); @@ -659,7 +661,8 @@ class RepeatedArrayFactory { } template - enable_if_binary_view_like Visit(const T& type) { + requires arrow_binary_view_like + Status Visit(const T& type) { std::string_view value{*scalar().value}; auto s = util::ToBinaryView(value, 0, 0); RETURN_NOT_OK(FinishFixedWidth(&s, sizeof(s))); @@ -670,7 +673,8 @@ class RepeatedArrayFactory { } template - enable_if_var_size_list Visit(const T& type) { + requires arrow_var_length_list + Status Visit(const T& type) { using ArrayType = typename TypeTraits::ArrayType; ArrayVector values(length_, scalar().value); @@ -685,7 +689,8 @@ class RepeatedArrayFactory { } template - enable_if_list_view Visit(const T& type) { + requires arrow_list_view + Status Visit(const T& type) { using ScalarType = typename TypeTraits::ScalarType; using ArrayType = typename TypeTraits::ArrayType; diff --git a/cpp/src/arrow/array/validate.cc b/cpp/src/arrow/array/validate.cc index bd0d00126d51..6b5a04c2fdeb 100644 --- a/cpp/src/arrow/array/validate.cc +++ b/cpp/src/arrow/array/validate.cc @@ -81,7 +81,8 @@ struct BoundsChecker { } template - enable_if_integer Visit(const IntegerType&) { + requires arrow_integer + Status Visit(const IntegerType&) { using c_type = typename IntegerType::c_type; int64_t i = 0; diff --git a/cpp/src/arrow/buffer_builder.h b/cpp/src/arrow/buffer_builder.h index e9177c656c02..45d88452562b 100644 --- a/cpp/src/arrow/buffer_builder.h +++ b/cpp/src/arrow/buffer_builder.h @@ -223,14 +223,13 @@ class ARROW_EXPORT BufferBuilder { int64_t alignment_; }; -template +template class TypedBufferBuilder; /// \brief A BufferBuilder for building a buffer of arithmetic elements template -class TypedBufferBuilder< - T, typename std::enable_if::value || - std::is_standard_layout::value>::type> { + requires(std::is_arithmetic_v || std::is_standard_layout_v) +class TypedBufferBuilder { public: explicit TypedBufferBuilder(MemoryPool* pool = default_memory_pool(), int64_t alignment = kDefaultBufferAlignment) diff --git a/cpp/src/arrow/builder.cc b/cpp/src/arrow/builder.cc index 1a6a718c15e1..2cd4625f1971 100644 --- a/cpp/src/arrow/builder.cc +++ b/cpp/src/arrow/builder.cc @@ -195,7 +195,8 @@ struct DictionaryBuilderCase { struct MakeBuilderImpl { template - enable_if_not_nested Visit(const T& t) { + requires(!arrow_nested) + Status Visit(const T& t) { out.reset(new typename TypeTraits::BuilderType(type, pool)); return Status::OK(); } diff --git a/cpp/src/arrow/compare.cc b/cpp/src/arrow/compare.cc index 26f56d9b588c..2bc5d6e22ccb 100644 --- a/cpp/src/arrow/compare.cc +++ b/cpp/src/arrow/compare.cc @@ -240,12 +240,14 @@ class RangeDataEqualsImpl { Status Visit(const NullType&) { return Status::OK(); } template - enable_if_primitive_ctype Visit(const TypeClass& type) { + requires arrow_primitive_ctype + Status Visit(const TypeClass& type) { return ComparePrimitive(type); } template - enable_if_t::value, Status> Visit(const TypeClass& type) { + requires arrow_temporal + Status Visit(const TypeClass& type) { return ComparePrimitive(type); } @@ -739,10 +741,8 @@ class TypeEqualsVisitor { } template - enable_if_t::value || is_primitive_ctype::value || - is_base_binary_type::value, - Status> - Visit(const T&) { + requires(arrow_null || arrow_primitive_ctype || arrow_base_binary) + Status Visit(const T&) { result_ = true; return Status::OK(); } @@ -753,17 +753,16 @@ class TypeEqualsVisitor { } template - enable_if_interval Visit(const T& left) { + requires arrow_interval + Status Visit(const T& left) { const auto& right = checked_cast(right_); result_ = right.interval_type() == left.interval_type(); return Status::OK(); } template - enable_if_t::value || is_date_type::value || - is_duration_type::value, - Status> - Visit(const T& left) { + requires(arrow_time || arrow_date || arrow_duration) + Status Visit(const T& left) { const auto& right = checked_cast(right_); result_ = left.unit() == right.unit(); return Status::OK(); @@ -789,8 +788,8 @@ class TypeEqualsVisitor { } template - enable_if_t::value || is_list_view_type::value, Status> Visit( - const T& left) { + requires(arrow_list || arrow_list_view) + Status Visit(const T& left) { std::shared_ptr left_field = left.field(0); std::shared_ptr right_field = checked_cast(right_).field(0); bool equal_names = !check_metadata_ || (left_field->name() == right_field->name()); @@ -804,7 +803,8 @@ class TypeEqualsVisitor { } template - enable_if_t::value, Status> Visit(const T& left) { + requires arrow_struct + Status Visit(const T& left) { return VisitChildren(left); } @@ -904,10 +904,9 @@ class ScalarEqualsVisitor { } template - typename std::enable_if<(is_primitive_ctype::value || - is_temporal_type::value), - Status>::type - Visit(const T& left_) { + requires(arrow_primitive_ctype || + arrow_temporal) + Status Visit(const T& left_) { const auto& right = checked_cast(right_); result_ = right.value == left_.value; return Status::OK(); @@ -920,7 +919,8 @@ class ScalarEqualsVisitor { Status Visit(const HalfFloatScalar& left) { return CompareFloating(left); } template - enable_if_t::value, Status> Visit(const T& left) { + requires std::is_base_of_v + Status Visit(const T& left) { const auto& right = checked_cast(right_); result_ = internal::SharedPtrEquals(left.value, right.value); return Status::OK(); diff --git a/cpp/src/arrow/compute/expression.h b/cpp/src/arrow/compute/expression.h index b8ce50675c8c..00ad47d2d4c2 100644 --- a/cpp/src/arrow/compute/expression.h +++ b/cpp/src/arrow/compute/expression.h @@ -161,8 +161,8 @@ ARROW_EXPORT Expression call(std::string function, std::vector arguments, std::shared_ptr options = NULLPTR); -template ::value>::type> +template + requires std::is_base_of_v Expression call(std::string function, std::vector arguments, Options options) { return call(std::move(function), std::move(arguments), diff --git a/cpp/src/arrow/compute/function_internal.h b/cpp/src/arrow/compute/function_internal.h index 7bea4043a5f2..79220cc5b57e 100644 --- a/cpp/src/arrow/compute/function_internal.h +++ b/cpp/src/arrow/compute/function_internal.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include #include @@ -30,6 +31,7 @@ #include "arrow/result.h" #include "arrow/scalar.h" #include "arrow/status.h" +#include "arrow/type_traits.h" #include "arrow/util/checked_cast.h" #include "arrow/util/key_value_metadata.h" #include "arrow/util/reflection_internal.h" @@ -97,16 +99,16 @@ ARROW_EXPORT Result> DeserializeFunctionOptions(const Buffer& buffer); template -static inline enable_if_t::value, std::string> GenericToString( - const T& value) { + requires(!has_enum_traits::value) +static inline std::string GenericToString(const T& value) { std::stringstream ss; ss << value; return ss.str(); } template -static inline enable_if_t::value, std::string> GenericToString( - const std::optional& value) { + requires(!has_enum_traits::value) +static inline std::string GenericToString(const std::optional& value) { return value.has_value() ? GenericToString(value.value()) : "nullopt"; } @@ -119,8 +121,8 @@ static inline std::string GenericToString(const std::string& value) { } template -static inline enable_if_t::value, std::string> GenericToString( - const T value) { + requires has_enum_traits::value +static inline std::string GenericToString(const T value) { return EnumTraits::value_name(value); } @@ -256,21 +258,20 @@ GenericTypeSingleton() { } template -static inline enable_if_same, - std::shared_ptr> -GenericTypeSingleton() { + requires std::same_as> +static inline std::shared_ptr GenericTypeSingleton() { return map(binary(), binary()); } template -static inline enable_if_t::value, std::shared_ptr> -GenericTypeSingleton() { + requires has_enum_traits::value +static inline std::shared_ptr GenericTypeSingleton() { return TypeTraits::Type>::type_singleton(); } template -static inline enable_if_same> -GenericTypeSingleton() { + requires std::same_as +static inline std::shared_ptr GenericTypeSingleton() { std::vector> fields; fields.emplace_back(new Field("target", GenericTypeSingleton())); fields.emplace_back(new Field("order", GenericTypeSingleton())); @@ -294,7 +295,8 @@ static inline Result> GenericToScalar(const FieldRef& re return MakeScalar(ref.ToDotPath()); } -template ::value>> +template + requires has_enum_traits::value static inline Result> GenericToScalar(const T value) { using CType = typename EnumTraits::CType; return GenericToScalar(static_cast(value)); @@ -389,8 +391,8 @@ static inline Result> GenericToScalar( } template -static inline enable_if_primitive_ctype::ArrowType, Result> -GenericFromScalar(const std::shared_ptr& value) { + requires arrow_primitive_ctype::ArrowType> +static inline Result GenericFromScalar(const std::shared_ptr& value) { using ArrowType = typename CTypeTraits::ArrowType; using ScalarType = typename TypeTraits::ScalarType; if (value->type->id() != ArrowType::type_id) { @@ -403,19 +405,16 @@ GenericFromScalar(const std::shared_ptr& value) { } template -static inline enable_if_primitive_ctype::Type, Result> -GenericFromScalar(const std::shared_ptr& value) { + requires arrow_primitive_ctype::Type> +static inline Result GenericFromScalar(const std::shared_ptr& value) { ARROW_ASSIGN_OR_RAISE(auto raw_val, GenericFromScalar::CType>(value)); return ValidateEnumValue(raw_val); } -template -using enable_if_same_result = enable_if_same>; - template -static inline enable_if_same_result GenericFromScalar( - const std::shared_ptr& value) { + requires std::same_as +static inline Result GenericFromScalar(const std::shared_ptr& value) { if (!is_base_binary_like(value->type->id())) { return Status::Invalid("Expected binary-like type but got ", value->type->ToString()); } @@ -425,15 +424,15 @@ static inline enable_if_same_result GenericFromScalar( } template -static inline enable_if_same_result GenericFromScalar( - const std::shared_ptr& value) { + requires std::same_as +static inline Result GenericFromScalar(const std::shared_ptr& value) { ARROW_ASSIGN_OR_RAISE(auto path, GenericFromScalar(value)); return FieldRef::FromDotPath(path); } template -static inline enable_if_same_result GenericFromScalar( - const std::shared_ptr& value) { + requires std::same_as +static inline Result GenericFromScalar(const std::shared_ptr& value) { if (value->type->id() != Type::STRUCT) { return Status::Invalid("Expected type STRUCT but got ", value->type->id()); } @@ -447,26 +446,26 @@ static inline enable_if_same_result GenericFromScalar( } template -static inline enable_if_same_result> GenericFromScalar( - const std::shared_ptr& value) { + requires std::same_as> +static inline Result GenericFromScalar(const std::shared_ptr& value) { return value->type; } template -static inline enable_if_same_result GenericFromScalar( - const std::shared_ptr& value) { + requires std::same_as +static inline Result GenericFromScalar(const std::shared_ptr& value) { return value->type; } template -static inline enable_if_same_result> GenericFromScalar( - const std::shared_ptr& value) { + requires std::same_as> +static inline Result GenericFromScalar(const std::shared_ptr& value) { return value; } template -static inline enable_if_same_result> -GenericFromScalar(const std::shared_ptr& value) { + requires std::same_as> +static inline Result GenericFromScalar(const std::shared_ptr& value) { auto ty = GenericTypeSingleton>(); if (!value->type->Equals(ty)) { return Status::Invalid("Expected ", ty->ToString(), " but got ", @@ -486,8 +485,8 @@ GenericFromScalar(const std::shared_ptr& value) { } template -static inline enable_if_same_result GenericFromScalar( - const std::shared_ptr& value) { + requires std::same_as +static inline Result GenericFromScalar(const std::shared_ptr& value) { if (value->type->id() == Type::LIST) { const auto& holder = checked_cast(*value); return holder.value; @@ -504,8 +503,8 @@ template <> constexpr inline bool is_optional_v = true; template -static inline std::enable_if_t, Result> GenericFromScalar( - const std::shared_ptr& value) { + requires is_optional_v +static inline Result GenericFromScalar(const std::shared_ptr& value) { using value_type = typename T::value_type; if (value->type->id() == Type::NA) { return std::nullopt; @@ -514,8 +513,8 @@ static inline std::enable_if_t, Result> GenericFromScalar( } template -static enable_if_same::ArrowType, ListType, Result> -GenericFromScalar(const std::shared_ptr& value) { + requires std::same_as::ArrowType, ListType> +static Result GenericFromScalar(const std::shared_ptr& value) { using ValueType = typename T::value_type; if (value->type->id() != Type::LIST) { return Status::Invalid("Expected type LIST but got ", value->type->ToString()); diff --git a/cpp/src/arrow/compute/kernels/aggregate_basic.cc b/cpp/src/arrow/compute/kernels/aggregate_basic.cc index 03fba53ac02d..204eeeda284e 100644 --- a/cpp/src/arrow/compute/kernels/aggregate_basic.cc +++ b/cpp/src/arrow/compute/kernels/aggregate_basic.cc @@ -416,15 +416,15 @@ struct ProductInit { return Status::OK(); } - template - enable_if_number Visit(const Type&) { + template + Status Visit(const Type&) { auto ty = TypeTraits::AccType>::type_singleton(); state.reset(new ProductImpl(ty, options)); return Status::OK(); } - template - enable_if_decimal Visit(const Type&) { + template + Status Visit(const Type&) { state.reset(new ProductImpl(type, options)); return Status::OK(); } @@ -777,14 +777,14 @@ struct IndexInit { return Status::OK(); } - template - enable_if_number Visit(const Type&) { + template + Status Visit(const Type&) { state.reset(new IndexImpl(options, ctx->state())); return Status::OK(); } - template - enable_if_base_binary Visit(const Type&) { + template + Status Visit(const Type&) { state.reset(new IndexImpl(options, ctx->state())); return Status::OK(); } @@ -794,26 +794,26 @@ struct IndexInit { return Status::OK(); } - template - enable_if_decimal Visit(const Type&) { + template + Status Visit(const Type&) { state.reset(new IndexImpl(options, ctx->state())); return Status::OK(); } - template - enable_if_date Visit(const Type&) { + template + Status Visit(const Type&) { state.reset(new IndexImpl(options, ctx->state())); return Status::OK(); } - template - enable_if_time Visit(const Type&) { + template + Status Visit(const Type&) { state.reset(new IndexImpl(options, ctx->state())); return Status::OK(); } - template - enable_if_timestamp Visit(const Type&) { + template + Status Visit(const Type&) { state.reset(new IndexImpl(options, ctx->state())); return Status::OK(); } diff --git a/cpp/src/arrow/compute/kernels/aggregate_basic.inc.cc b/cpp/src/arrow/compute/kernels/aggregate_basic.inc.cc index 3733f415a048..fe843167ba5e 100644 --- a/cpp/src/arrow/compute/kernels/aggregate_basic.inc.cc +++ b/cpp/src/arrow/compute/kernels/aggregate_basic.inc.cc @@ -188,8 +188,8 @@ struct SumLikeInit { return Status::OK(); } - template - enable_if_number Visit(const Type&) { + template + Status Visit(const Type&) { auto ty = TypeTraits::SumType>::type_singleton(); state.reset(new KernelClass(ty, options)); return Status::OK(); @@ -197,8 +197,8 @@ struct SumLikeInit { // By default, we widen the decimal to max precision for SumLikes // However, this may not be the desired behaviour (see, e.g., MeanKernelInit) - template - enable_if_decimal Visit(const Type&) { + template + Status Visit(const Type&) { if (PromoteDecimal()) { ARROW_ASSIGN_OR_RAISE(auto ty, WidenDecimalToMaxPrecision(type)); state.reset(new KernelClass(ty, options)); @@ -223,12 +223,12 @@ struct SumLikeInit { // ---------------------------------------------------------------------- // Mean implementation -template +template struct MeanImpl; template -struct MeanImpl> - : public SumImpl { + requires arrow_decimal +struct MeanImpl : public SumImpl { using SumImpl::SumImpl; using SumImpl::options; using SumCType = typename SumImpl::SumCType; @@ -260,8 +260,8 @@ struct MeanImpl> }; template -struct MeanImpl::value>> + requires(!arrow_decimal) +struct MeanImpl // Override the ResultType of SumImpl because we need to use double for intermediate // sum to prevent integer overflows : public SumImpl { @@ -302,11 +302,11 @@ struct MeanKernelInit : public SumLikeInit { // ---------------------------------------------------------------------- // FirstLast implementation -template +template struct FirstLastState {}; -template -struct FirstLastState> { +template +struct FirstLastState { using ThisType = FirstLastState; using T = typename ArrowType::c_type; using ScalarType = typename TypeTraits::ScalarType; @@ -337,8 +337,8 @@ struct FirstLastState> { bool has_any_values = false; }; -template -struct FirstLastState> { +template +struct FirstLastState { using ThisType = FirstLastState; using T = typename ArrowType::c_type; using ScalarType = typename TypeTraits::ScalarType; @@ -377,8 +377,8 @@ struct FirstLastState> { bool has_any_values = false; }; -template -struct FirstLastState> { +template +struct FirstLastState { using ThisType = FirstLastState; using T = typename ArrowType::c_type; using ScalarType = typename TypeTraits::ScalarType; @@ -410,9 +410,8 @@ struct FirstLastState> { }; template -struct FirstLastState::value || - std::is_same::value>> { + requires(arrow_base_binary || std::same_as) +struct FirstLastState { using ThisType = FirstLastState; using ScalarType = typename TypeTraits::ScalarType; @@ -593,28 +592,29 @@ struct FirstLastInitState { return Status::OK(); } - template - enable_if_physical_integer Visit(const Type&) { + template + Status Visit(const Type&) { using PhysicalType = typename Type::PhysicalType; state.reset(new FirstLastImpl(out_type, options)); return Status::OK(); } - template - enable_if_physical_floating_point Visit(const Type&) { + template + Status Visit(const Type&) { using PhysicalType = typename Type::PhysicalType; state.reset(new FirstLastImpl(out_type, options)); return Status::OK(); } - template - enable_if_base_binary Visit(const Type&) { + template + Status Visit(const Type&) { state.reset(new FirstLastImpl(out_type, options)); return Status::OK(); } template - enable_if_t::value, Status> Visit(const Type&) { + requires std::same_as + Status Visit(const Type&) { state.reset(new FirstLastImpl(out_type, options)); return Status::OK(); } @@ -628,11 +628,11 @@ struct FirstLastInitState { // ---------------------------------------------------------------------- // MinMax implementation -template +template struct MinMaxState {}; -template -struct MinMaxState> { +template +struct MinMaxState { using ThisType = MinMaxState; using T = typename ArrowType::c_type; @@ -653,8 +653,8 @@ struct MinMaxState> { bool has_nulls = false; }; -template -struct MinMaxState> { +template +struct MinMaxState { using ThisType = MinMaxState; using T = typename ArrowType::c_type; using ScalarType = typename TypeTraits::ScalarType; @@ -676,8 +676,8 @@ struct MinMaxState> { bool has_nulls = false; }; -template -struct MinMaxState> { +template +struct MinMaxState { using ThisType = MinMaxState; using T = typename ArrowType::c_type; using ScalarType = typename TypeTraits::ScalarType; @@ -699,8 +699,8 @@ struct MinMaxState> { bool has_nulls = false; }; -template -struct MinMaxState> { +template +struct MinMaxState { using ThisType = MinMaxState; using T = typename TypeTraits::CType; using ScalarType = typename TypeTraits::ScalarType; @@ -729,9 +729,8 @@ struct MinMaxState> { }; template -struct MinMaxState::value || - std::is_same::value>> { + requires(arrow_base_binary || std::same_as) +struct MinMaxState { using ThisType = MinMaxState; using ScalarType = typename TypeTraits::ScalarType; @@ -1009,27 +1008,27 @@ struct MinMaxInitState { return Status::OK(); } - template - enable_if_physical_integer Visit(const Type&) { + template + Status Visit(const Type&) { using PhysicalType = typename Type::PhysicalType; state.reset(new MinMaxImpl(out_type, options)); return Status::OK(); } - template - enable_if_floating_point Visit(const Type&) { + template + Status Visit(const Type&) { state.reset(new MinMaxImpl(out_type, options)); return Status::OK(); } - template - enable_if_base_binary Visit(const Type&) { + template + Status Visit(const Type&) { state.reset(new MinMaxImpl(out_type, options)); return Status::OK(); } - template - enable_if_fixed_size_binary Visit(const Type&) { + template + Status Visit(const Type&) { state.reset(new MinMaxImpl(out_type, options)); return Status::OK(); } diff --git a/cpp/src/arrow/compute/kernels/aggregate_internal.h b/cpp/src/arrow/compute/kernels/aggregate_internal.h index 126f2891e212..81baec8fccf8 100644 --- a/cpp/src/arrow/compute/kernels/aggregate_internal.h +++ b/cpp/src/arrow/compute/kernels/aggregate_internal.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include "arrow/compute/kernels/util_internal.h" @@ -30,52 +31,52 @@ namespace arrow::compute::internal { // Find the largest compatible primitive type for a primitive type. -template +template struct FindAccumulatorType {}; -template -struct FindAccumulatorType> { +template +struct FindAccumulatorType { using Type = UInt64Type; }; -template -struct FindAccumulatorType> { +template +struct FindAccumulatorType { using Type = Int64Type; }; -template -struct FindAccumulatorType> { +template +struct FindAccumulatorType { using Type = UInt64Type; }; -template -struct FindAccumulatorType> { +template +struct FindAccumulatorType { using Type = DoubleType; }; -template -struct FindAccumulatorType> { +template +struct FindAccumulatorType { using Type = Decimal32Type; }; -template -struct FindAccumulatorType> { +template +struct FindAccumulatorType { using Type = Decimal64Type; }; -template -struct FindAccumulatorType> { +template +struct FindAccumulatorType { using Type = Decimal128Type; }; -template -struct FindAccumulatorType> { +template +struct FindAccumulatorType { using Type = Decimal256Type; }; // Helpers for implementing aggregations on decimals -template +template struct MultiplyTraits { using CType = typename TypeTraits::CType; @@ -86,8 +87,8 @@ struct MultiplyTraits { } }; -template -struct MultiplyTraits> { +template +struct MultiplyTraits { using CType = typename TypeTraits::CType; constexpr static CType one(const DataType& ty) { @@ -129,21 +130,21 @@ void AddAggKernel(std::shared_ptr sig, KernelInit init, using arrow::internal::VisitSetBitRunsVoid; -template +template struct GetSumType; -template -struct GetSumType> { +template +struct GetSumType { using SumType = double; }; -template -struct GetSumType> { +template +struct GetSumType { using SumType = arrow::internal::int128_t; }; -template -struct GetSumType> { +template +struct GetSumType { using SumType = typename TypeTraits::CType; }; @@ -156,8 +157,8 @@ struct GetSumType> { // https://en.wikipedia.org/wiki/Pairwise_summation template -enable_if_t::value, SumType> SumArray( - const ArraySpan& data, ValueFunc&& func) { + requires std::floating_point +SumType SumArray(const ArraySpan& data, ValueFunc&& func) { using arrow::internal::VisitSetBitRunsVoid; const int64_t data_size = data.length - data.GetNullCount(); @@ -234,8 +235,8 @@ enable_if_t::value, SumType> SumArray( // naive summation for integers and decimals template -enable_if_t::value, SumType> SumArray( - const ArraySpan& data, ValueFunc&& func) { + requires(!std::floating_point) +SumType SumArray(const ArraySpan& data, ValueFunc&& func) { using arrow::internal::VisitSetBitRunsVoid; SumType sum = 0; diff --git a/cpp/src/arrow/compute/kernels/aggregate_mode.cc b/cpp/src/arrow/compute/kernels/aggregate_mode.cc index fbafa663b864..f62a53635443 100644 --- a/cpp/src/arrow/compute/kernels/aggregate_mode.cc +++ b/cpp/src/arrow/compute/kernels/aggregate_mode.cc @@ -260,13 +260,14 @@ struct SortModer { using CType = typename TypeTraits::CType; using Allocator = arrow::stl::allocator; - template - static enable_if_floating_point GetNan() { + template + static CType GetNan() { return static_cast(NAN); } template - static enable_if_t::value, CType> GetNan() { + requires(!arrow_floating_point) + static CType GetNan() { DCHECK(false); return static_cast(0); } @@ -381,7 +382,7 @@ struct CountOrSortModer { } }; -template +template struct Moder; template <> @@ -402,18 +403,18 @@ struct Moder { }; template -struct Moder::value && - (sizeof(typename InType::c_type) > 1))>> { + requires(arrow_integer && (sizeof(typename InType::c_type) > 1)) +struct Moder { CountOrSortModer impl; }; -template -struct Moder> { +template +struct Moder { SortModer impl; }; -template -struct Moder> { +template +struct Moder { SortModer impl; }; diff --git a/cpp/src/arrow/compute/kernels/aggregate_quantile.cc b/cpp/src/arrow/compute/kernels/aggregate_quantile.cc index 4e3894d2f206..2201a7ed1785 100644 --- a/cpp/src/arrow/compute/kernels/aggregate_quantile.cc +++ b/cpp/src/arrow/compute/kernels/aggregate_quantile.cc @@ -168,7 +168,7 @@ struct SortQuantiler { CopyNonNullValues(container, in_buffer->data()); // drop nan - if (is_floating_type::value) { + if constexpr (arrow_floating_point) { const auto& it = std::remove_if(in_buffer->begin(), in_buffer->end(), [](CType v) { return v != v; }); in_buffer->resize(it - in_buffer->begin()); @@ -448,7 +448,7 @@ struct CountOrSortQuantiler { } }; -template +template struct ExactQuantiler; template <> @@ -464,18 +464,20 @@ struct ExactQuantiler { }; template -struct ExactQuantiler::value && - (sizeof(typename InType::c_type) > 1))>> { + requires(arrow_integer && (sizeof(typename InType::c_type) > 1)) +struct ExactQuantiler { CountOrSortQuantiler impl; }; template -struct ExactQuantiler::value>> { + requires arrow_floating_point +struct ExactQuantiler { SortQuantiler impl; }; template -struct ExactQuantiler::value>> { + requires arrow_decimal +struct ExactQuantiler { SortQuantiler impl; }; diff --git a/cpp/src/arrow/compute/kernels/aggregate_tdigest.cc b/cpp/src/arrow/compute/kernels/aggregate_tdigest.cc index 7ebc85941135..a5baf62e6e66 100644 --- a/cpp/src/arrow/compute/kernels/aggregate_tdigest.cc +++ b/cpp/src/arrow/compute/kernels/aggregate_tdigest.cc @@ -147,14 +147,14 @@ struct TDigestInitState { return Status::NotImplemented("No tdigest implemented"); } - template - enable_if_number Visit(const Type&) { + template + Status Visit(const Type&) { state.reset(new TDigestImpl(options, in_type)); return Status::OK(); } - template - enable_if_decimal Visit(const Type&) { + template + Status Visit(const Type&) { state.reset(new TDigestImpl(options, in_type)); return Status::OK(); } diff --git a/cpp/src/arrow/compute/kernels/aggregate_test.cc b/cpp/src/arrow/compute/kernels/aggregate_test.cc index c5ba012d7674..82f830028301 100644 --- a/cpp/src/arrow/compute/kernels/aggregate_test.cc +++ b/cpp/src/arrow/compute/kernels/aggregate_test.cc @@ -2260,9 +2260,8 @@ struct MinMaxResult { bool is_valid = false; }; -template -static enable_if_integer> NaiveMinMax( - const Array& array) { +template +static MinMaxResult NaiveMinMax(const Array& array) { using T = typename ArrowType::c_type; using ArrayType = typename TypeTraits::ArrayType; @@ -2299,9 +2298,8 @@ static enable_if_integer> NaiveMinMax( return result; } -template -static enable_if_floating_point> NaiveMinMax( - const Array& array) { +template +static MinMaxResult NaiveMinMax(const Array& array) { using T = typename ArrowType::c_type; using ArrayType = typename TypeTraits::ArrayType; diff --git a/cpp/src/arrow/compute/kernels/base_arithmetic_internal.h b/cpp/src/arrow/compute/kernels/base_arithmetic_internal.h index b4840061ae75..8784ab51fd02 100644 --- a/cpp/src/arrow/compute/kernels/base_arithmetic_internal.h +++ b/cpp/src/arrow/compute/kernels/base_arithmetic_internal.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include "arrow/compute/api_scalar.h" #include "arrow/compute/kernels/common_internal.h" @@ -42,35 +43,44 @@ using util::Float16; namespace compute { namespace internal { +template +concept arithmetic_decimal_value = + std::same_as || std::same_as || + std::same_as || std::same_as; + +template +concept arithmetic_half_float_value = std::same_as; + struct Add { template - static constexpr enable_if_floating_value Call(KernelContext*, Arg0 left, Arg1 right, - Status*) { + requires std::floating_point + static constexpr T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { return left + right; } template - static constexpr enable_if_unsigned_integer_value Call(KernelContext*, Arg0 left, - Arg1 right, Status*) { + requires std::unsigned_integral + static constexpr T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { return left + right; } template - static constexpr enable_if_signed_integer_value Call(KernelContext*, Arg0 left, - Arg1 right, Status*) { + requires std::signed_integral + static constexpr T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { return arrow::internal::SafeSignedAdd(left, right); } template - static enable_if_decimal_value Call(KernelContext*, Arg0 left, Arg1 right, Status*) { + requires arithmetic_decimal_value + static T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { return left + right; } }; struct AddChecked { template - static enable_if_integer_value Call(KernelContext*, Arg0 left, Arg1 right, - Status* st) { + requires std::integral + static T Call(KernelContext*, Arg0 left, Arg1 right, Status* st) { static_assert(std::is_same::value && std::is_same::value, ""); T result = 0; if (ARROW_PREDICT_FALSE(AddWithOverflow(left, right, &result))) { @@ -80,14 +90,15 @@ struct AddChecked { } template - static enable_if_floating_value Call(KernelContext*, Arg0 left, Arg1 right, - Status*) { + requires std::floating_point + static T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { static_assert(std::is_same::value && std::is_same::value, ""); return left + right; } template - static enable_if_decimal_value Call(KernelContext*, Arg0 left, Arg1 right, Status*) { + requires arithmetic_decimal_value + static T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { return left + right; } }; @@ -125,34 +136,34 @@ struct AddTimeDurationChecked { struct AbsoluteValue { template - static constexpr enable_if_floating_value Call(KernelContext*, Arg arg, - Status*) { + requires std::floating_point + static constexpr T Call(KernelContext*, Arg arg, Status*) { return std::fabs(arg); } template - static constexpr enable_if_unsigned_integer_value Call(KernelContext*, Arg arg, - Status*) { + requires std::unsigned_integral + static constexpr T Call(KernelContext*, Arg arg, Status*) { return arg; } template - static constexpr enable_if_signed_integer_value Call(KernelContext*, Arg arg, - Status* st) { + requires std::signed_integral + static constexpr T Call(KernelContext*, Arg arg, Status* st) { return (arg < 0) ? arrow::internal::SafeSignedNegate(arg) : arg; } template - static constexpr enable_if_decimal_value Call(KernelContext*, Arg arg, - Status*) { + requires arithmetic_decimal_value + static constexpr T Call(KernelContext*, Arg arg, Status*) { return arg.Abs(); } }; struct AbsoluteValueChecked { template - static enable_if_signed_integer_value Call(KernelContext*, Arg arg, - Status* st) { + requires std::signed_integral + static T Call(KernelContext*, Arg arg, Status* st) { static_assert(std::is_same::value, ""); if (arg == std::numeric_limits::min()) { *st = Status::Invalid("overflow"); @@ -162,57 +173,58 @@ struct AbsoluteValueChecked { } template - static enable_if_unsigned_integer_value Call(KernelContext* ctx, Arg arg, - Status* st) { + requires std::unsigned_integral + static T Call(KernelContext* ctx, Arg arg, Status* st) { static_assert(std::is_same::value, ""); return arg; } template - static constexpr enable_if_floating_value Call(KernelContext*, Arg arg, - Status* st) { + requires std::floating_point + static constexpr T Call(KernelContext*, Arg arg, Status* st) { static_assert(std::is_same::value, ""); return std::fabs(arg); } template - static constexpr enable_if_decimal_value Call(KernelContext*, Arg arg, - Status*) { + requires arithmetic_decimal_value + static constexpr T Call(KernelContext*, Arg arg, Status*) { return arg.Abs(); } }; struct Subtract { template - static constexpr enable_if_floating_value Call(KernelContext*, Arg0 left, Arg1 right, - Status*) { + requires std::floating_point + static constexpr T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { static_assert(std::is_same::value && std::is_same::value, ""); return left - right; } template - static constexpr enable_if_unsigned_integer_value Call(KernelContext*, Arg0 left, - Arg1 right, Status*) { + requires std::unsigned_integral + static constexpr T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { static_assert(std::is_same::value && std::is_same::value, ""); return left - right; } template - static constexpr enable_if_signed_integer_value Call(KernelContext*, Arg0 left, - Arg1 right, Status*) { + requires std::signed_integral + static constexpr T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { return arrow::internal::SafeSignedSubtract(left, right); } template - static enable_if_decimal_value Call(KernelContext*, Arg0 left, Arg1 right, Status*) { + requires arithmetic_decimal_value + static T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { return left + (-right); } }; struct SubtractChecked { template - static enable_if_integer_value Call(KernelContext*, Arg0 left, Arg1 right, - Status* st) { + requires std::integral + static T Call(KernelContext*, Arg0 left, Arg1 right, Status* st) { T result = 0; if (ARROW_PREDICT_FALSE(SubtractWithOverflow(left, right, &result))) { *st = Status::Invalid("overflow"); @@ -221,14 +233,15 @@ struct SubtractChecked { } template - static enable_if_floating_value Call(KernelContext*, Arg0 left, Arg1 right, - Status*) { + requires std::floating_point + static T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { static_assert(std::is_same::value && std::is_same::value, ""); return left - right; } template - static enable_if_decimal_value Call(KernelContext*, Arg0 left, Arg1 right, Status*) { + requires arithmetic_decimal_value + static T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { return left + (-right); } }; @@ -298,22 +311,20 @@ struct Multiply { static_assert(std::is_same::value, ""); template - static constexpr enable_if_floating_value Call(KernelContext*, T left, T right, - Status*) { + requires std::floating_point + static constexpr T Call(KernelContext*, T left, T right, Status*) { return left * right; } template - static constexpr enable_if_t< - is_unsigned_integer_value::value && !std::is_same::value, T> - Call(KernelContext*, T left, T right, Status*) { + requires(std::unsigned_integral && !std::same_as) + static constexpr T Call(KernelContext*, T left, T right, Status*) { return left * right; } template - static constexpr enable_if_t< - is_signed_integer_value::value && !std::is_same::value, T> - Call(KernelContext*, T left, T right, Status*) { + requires(std::signed_integral && !std::same_as) + static constexpr T Call(KernelContext*, T left, T right, Status*) { return to_unsigned(left) * to_unsigned(right); } @@ -322,26 +333,27 @@ struct Multiply { // behaviour). Therefore we first cast to 32 bit unsigned integers where overflow is // well defined. template - static constexpr enable_if_same Call(KernelContext*, int16_t left, - int16_t right, Status*) { + requires std::same_as + static constexpr T Call(KernelContext*, int16_t left, int16_t right, Status*) { return static_cast(left) * static_cast(right); } template - static constexpr enable_if_same Call(KernelContext*, uint16_t left, - uint16_t right, Status*) { + requires std::same_as + static constexpr T Call(KernelContext*, uint16_t left, uint16_t right, Status*) { return static_cast(left) * static_cast(right); } template - static enable_if_decimal_value Call(KernelContext*, Arg0 left, Arg1 right, Status*) { + requires arithmetic_decimal_value + static T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { return left * right; } }; struct MultiplyChecked { template - static enable_if_integer_value Call(KernelContext*, Arg0 left, Arg1 right, - Status* st) { + requires std::integral + static T Call(KernelContext*, Arg0 left, Arg1 right, Status* st) { static_assert(std::is_same::value && std::is_same::value, ""); T result = 0; if (ARROW_PREDICT_FALSE(MultiplyWithOverflow(left, right, &result))) { @@ -351,28 +363,29 @@ struct MultiplyChecked { } template - static enable_if_floating_value Call(KernelContext*, Arg0 left, Arg1 right, - Status*) { + requires std::floating_point + static T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { static_assert(std::is_same::value && std::is_same::value, ""); return left * right; } template - static enable_if_decimal_value Call(KernelContext*, Arg0 left, Arg1 right, Status*) { + requires arithmetic_decimal_value + static T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { return left * right; } }; struct Divide { template - static enable_if_floating_value Call(KernelContext*, Arg0 left, Arg1 right, - Status*) { + requires std::floating_point + static T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { return left / right; } template - static enable_if_integer_value Call(KernelContext*, Arg0 left, Arg1 right, - Status* st) { + requires std::integral + static T Call(KernelContext*, Arg0 left, Arg1 right, Status* st) { T result; if (ARROW_PREDICT_FALSE(DivideWithOverflow(left, right, &result))) { if (right == 0) { @@ -385,8 +398,8 @@ struct Divide { } template - static enable_if_decimal_value Call(KernelContext*, Arg0 left, Arg1 right, - Status* st) { + requires arithmetic_decimal_value + static T Call(KernelContext*, Arg0 left, Arg1 right, Status* st) { if (right == Arg1()) { *st = Status::Invalid("Divide by zero"); return T(); @@ -398,8 +411,8 @@ struct Divide { struct DivideChecked { template - static enable_if_integer_value Call(KernelContext*, Arg0 left, Arg1 right, - Status* st) { + requires std::integral + static T Call(KernelContext*, Arg0 left, Arg1 right, Status* st) { static_assert(std::is_same::value && std::is_same::value, ""); T result; if (ARROW_PREDICT_FALSE(DivideWithOverflow(left, right, &result))) { @@ -413,8 +426,8 @@ struct DivideChecked { } template - static enable_if_floating_value Call(KernelContext*, Arg0 left, Arg1 right, - Status* st) { + requires std::floating_point + static T Call(KernelContext*, Arg0 left, Arg1 right, Status* st) { static_assert(std::is_same::value && std::is_same::value, ""); if (ARROW_PREDICT_FALSE(right == 0)) { *st = Status::Invalid("divide by zero"); @@ -424,22 +437,22 @@ struct DivideChecked { } template - static enable_if_decimal_value Call(KernelContext* ctx, Arg0 left, Arg1 right, - Status* st) { + requires arithmetic_decimal_value + static T Call(KernelContext* ctx, Arg0 left, Arg1 right, Status* st) { return Divide::Call(ctx, left, right, st); } }; struct FloatingDivide { template - static enable_if_floating_value Call(KernelContext*, Arg0 left, Arg1 right, - Status*) { + requires std::floating_point + static Arg0 Call(KernelContext*, Arg0 left, Arg1 right, Status*) { return left / right; } template - static enable_if_integer_value Call(KernelContext* ctx, Arg0 left, - Arg1 right, Status* st) { + requires std::integral + static double Call(KernelContext* ctx, Arg0 left, Arg1 right, Status* st) { static_assert(std::is_same::value); return Call(ctx, static_cast(left), static_cast(right), st); } @@ -449,8 +462,8 @@ struct FloatingDivide { struct FloatingDivideChecked { template - static enable_if_floating_value Call(KernelContext*, Arg0 left, Arg1 right, - Status* st) { + requires std::floating_point + static Arg0 Call(KernelContext*, Arg0 left, Arg1 right, Status* st) { static_assert(std::is_same::value && std::is_same::value); if (ARROW_PREDICT_FALSE(right == 0)) { *st = Status::Invalid("divide by zero"); @@ -460,8 +473,8 @@ struct FloatingDivideChecked { } template - static enable_if_integer_value Call(KernelContext* ctx, Arg0 left, - Arg1 right, Status* st) { + requires std::integral + static double Call(KernelContext* ctx, Arg0 left, Arg1 right, Status* st) { static_assert(std::is_same::value); return Call(ctx, static_cast(left), static_cast(right), st); } @@ -470,38 +483,40 @@ struct FloatingDivideChecked { struct Negate { template - static constexpr enable_if_floating_value Call(KernelContext*, Arg arg, Status*) { + requires std::floating_point + static constexpr T Call(KernelContext*, Arg arg, Status*) { return -arg; } template - static constexpr enable_if_half_float_value Call(KernelContext*, Arg arg, Status*) { + requires arithmetic_half_float_value + static constexpr T Call(KernelContext*, Arg arg, Status*) { return -arg; } template - static constexpr enable_if_unsigned_integer_value Call(KernelContext*, Arg arg, - Status*) { + requires std::unsigned_integral + static constexpr T Call(KernelContext*, Arg arg, Status*) { return ~arg + 1; } template - static constexpr enable_if_signed_integer_value Call(KernelContext*, Arg arg, - Status*) { + requires std::signed_integral + static constexpr T Call(KernelContext*, Arg arg, Status*) { return arrow::internal::SafeSignedNegate(arg); } template - static constexpr enable_if_decimal_value Call(KernelContext*, Arg arg, - Status*) { + requires arithmetic_decimal_value + static constexpr T Call(KernelContext*, Arg arg, Status*) { return arg.Negate(); } }; struct NegateChecked { template - static enable_if_signed_integer_value Call(KernelContext*, Arg arg, - Status* st) { + requires std::signed_integral + static T Call(KernelContext*, Arg arg, Status* st) { static_assert(std::is_same::value, ""); T result = 0; if (ARROW_PREDICT_FALSE(NegateWithOverflow(arg, &result))) { @@ -511,8 +526,8 @@ struct NegateChecked { } template - static enable_if_unsigned_integer_value Call(KernelContext* ctx, Arg arg, - Status* st) { + requires std::unsigned_integral + static T Call(KernelContext* ctx, Arg arg, Status* st) { static_assert(std::is_same::value, ""); ARROW_DCHECK(false) << "This is included only for the purposes of instantiability " "from the arithmetic kernel generator"; @@ -520,21 +535,22 @@ struct NegateChecked { } template - static constexpr enable_if_floating_value Call(KernelContext*, Arg arg, - Status* st) { + requires std::floating_point + static constexpr T Call(KernelContext*, Arg arg, Status* st) { static_assert(std::is_same::value, ""); return -arg; } template - static constexpr enable_if_half_float_value Call(KernelContext*, Arg arg, Status*) { + requires arithmetic_half_float_value + static constexpr T Call(KernelContext*, Arg arg, Status*) { static_assert(std::is_same::value, ""); return -arg; } template - static constexpr enable_if_decimal_value Call(KernelContext*, Arg arg, - Status*) { + requires arithmetic_decimal_value + static constexpr T Call(KernelContext*, Arg arg, Status*) { return arg.Negate(); } }; @@ -569,7 +585,8 @@ struct Power { } template - static enable_if_integer_value Call(KernelContext*, T base, T exp, Status* st) { + requires std::integral + static T Call(KernelContext*, T base, T exp, Status* st) { if (exp < 0) { *st = Status::Invalid("integers to negative integer powers are not allowed"); return 0; @@ -578,15 +595,16 @@ struct Power { } template - static enable_if_floating_value Call(KernelContext*, T base, T exp, Status*) { + requires std::floating_point + static T Call(KernelContext*, T base, T exp, Status*) { return std::pow(base, exp); } }; struct PowerChecked { template - static enable_if_integer_value Call(KernelContext*, Arg0 base, Arg1 exp, - Status* st) { + requires std::integral + static T Call(KernelContext*, Arg0 base, Arg1 exp, Status* st) { if (exp < 0) { *st = Status::Invalid("integers to negative integer powers are not allowed"); return 0; @@ -611,7 +629,8 @@ struct PowerChecked { } template - static enable_if_floating_value Call(KernelContext*, Arg0 base, Arg1 exp, Status*) { + requires std::floating_point + static T Call(KernelContext*, Arg0 base, Arg1 exp, Status*) { static_assert(std::is_same::value && std::is_same::value, ""); return std::pow(base, exp); } @@ -619,7 +638,8 @@ struct PowerChecked { struct SquareRoot { template - static enable_if_floating_value Call(KernelContext*, Arg arg, Status*) { + requires std::floating_point + static T Call(KernelContext*, Arg arg, Status*) { static_assert(std::is_same::value, ""); if (arg < 0.0) { return std::numeric_limits::quiet_NaN(); @@ -630,7 +650,8 @@ struct SquareRoot { struct SquareRootChecked { template - static enable_if_floating_value Call(KernelContext*, Arg arg, Status* st) { + requires std::floating_point + static T Call(KernelContext*, Arg arg, Status* st) { static_assert(std::is_same::value, ""); if (arg < 0.0) { *st = Status::Invalid("square root of negative number"); @@ -642,14 +663,14 @@ struct SquareRootChecked { struct Sign { template - static constexpr enable_if_floating_value Call(KernelContext*, Arg arg, - Status*) { + requires std::floating_point + static constexpr T Call(KernelContext*, Arg arg, Status*) { return std::isnan(arg) ? arg : ((arg == 0) ? 0 : (std::signbit(arg) ? -1 : 1)); } template - static constexpr enable_if_half_float_value Call(KernelContext*, Arg arg, - Status*) { + requires arithmetic_half_float_value + static constexpr T Call(KernelContext*, Arg arg, Status*) { return arg.is_nan() ? arg : (arg.is_zero() ? Float16::zero() @@ -657,35 +678,35 @@ struct Sign { } template - static constexpr enable_if_unsigned_integer_value Call(KernelContext*, Arg arg, - Status*) { + requires std::unsigned_integral + static constexpr T Call(KernelContext*, Arg arg, Status*) { return (arg > 0) ? 1 : 0; } template - static constexpr enable_if_signed_integer_value Call(KernelContext*, Arg arg, - Status*) { + requires std::signed_integral + static constexpr T Call(KernelContext*, Arg arg, Status*) { return (arg > 0) ? 1 : ((arg == 0) ? 0 : -1); } template - static constexpr enable_if_decimal_value Call(KernelContext*, Arg arg, - Status*) { + requires arithmetic_decimal_value + static constexpr T Call(KernelContext*, Arg arg, Status*) { return (arg == 0) ? 0 : arg.Sign(); } }; struct Max { template - static constexpr enable_if_not_floating_value Call(KernelContext*, Arg0 arg0, - Arg1 arg1, Status*) { + requires(!std::floating_point) + static constexpr T Call(KernelContext*, Arg0 arg0, Arg1 arg1, Status*) { static_assert(std::is_same::value && std::is_same::value); return std::max(arg0, arg1); } template - static constexpr enable_if_floating_value Call(KernelContext*, Arg0 left, Arg1 right, - Status*) { + requires std::floating_point + static constexpr T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { static_assert(std::is_same::value && std::is_same::value); if (std::isnan(left)) { return right; @@ -699,15 +720,15 @@ struct Max { struct Min { template - static constexpr enable_if_not_floating_value Call(KernelContext*, Arg0 arg0, - Arg1 arg1, Status*) { + requires(!std::floating_point) + static constexpr T Call(KernelContext*, Arg0 arg0, Arg1 arg1, Status*) { static_assert(std::is_same::value && std::is_same::value); return std::min(arg0, arg1); } template - static constexpr enable_if_floating_value Call(KernelContext*, Arg0 left, Arg1 right, - Status*) { + requires std::floating_point + static constexpr T Call(KernelContext*, Arg0 left, Arg1 right, Status*) { static_assert(std::is_same::value && std::is_same::value); if (std::isnan(left)) { return right; diff --git a/cpp/src/arrow/compute/kernels/codegen_internal.h b/cpp/src/arrow/compute/kernels/codegen_internal.h index 15a946fbdbb8..0d254b3989ff 100644 --- a/cpp/src/arrow/compute/kernels/codegen_internal.h +++ b/cpp/src/arrow/compute/kernels/codegen_internal.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include #include @@ -123,11 +124,11 @@ struct KernelStateFromFunctionOptions : public KernelState { // ---------------------------------------------------------------------- // Input and output value type definitions -template +template struct GetViewType; -template -struct GetViewType> { +template +struct GetViewType { using T = typename Type::c_type; using PhysicalType = T; @@ -143,9 +144,9 @@ struct GetViewType { }; template -struct GetViewType::value || - is_fixed_size_binary_type::value || - is_binary_view_like_type::value>> { + requires(arrow_base_binary || arrow_fixed_size_binary || + arrow_binary_view_like) +struct GetViewType { using T = std::string_view; using PhysicalType = T; @@ -200,11 +201,11 @@ struct GetViewType { static T LogicalValue(T value) { return value; } }; -template +template struct GetOutputType; -template -struct GetOutputType> { +template +struct GetOutputType { using T = typename Type::c_type; }; @@ -213,8 +214,8 @@ struct GetOutputType { using T = Float16; }; -template -struct GetOutputType::value>> { +template +struct GetOutputType { using T = std::string; }; @@ -239,7 +240,7 @@ struct GetOutputType { }; // ---------------------------------------------------------------------- -// enable_if helpers for C types +// Local concepts for value-category and callback dispatch template using is_unsigned_integer_value = @@ -255,6 +256,8 @@ using is_integer_value = std::integral_constant::value || is_unsigned_integer_value::value>; +// Keep these local aliases for compatibility with neighboring kernel .cc files +// that still depend on codegen_internal.h for value-category SFINAE helpers. template using enable_if_signed_integer_value = enable_if_t::value, R>; @@ -290,13 +293,26 @@ template using enable_if_c_number_or_decimal = enable_if_t< (has_c_type::value && !is_boolean_type::value) || is_decimal_type::value, R>; +template +concept codegen_c_number_or_decimal = + (arrow_has_c_type && !arrow_boolean) || arrow_decimal; + +template +concept codegen_visit_returns_void = + std::same_as>; + +template +concept codegen_visit_returns_status = + std::same_as>; + // Iterator over various input array types, yielding a GetViewType -template +template struct ArrayIterator; template -struct ArrayIterator> { + requires codegen_c_number_or_decimal +struct ArrayIterator { using T = typename TypeTraits::ScalarType::ValueType; const T* values; @@ -313,8 +329,8 @@ struct ArrayIterator { T operator()() { return *values++; } }; -template -struct ArrayIterator> { +template +struct ArrayIterator { BitmapReader reader; explicit ArrayIterator(const ArraySpan& arr) @@ -326,8 +342,8 @@ struct ArrayIterator> { } }; -template -struct ArrayIterator> { +template +struct ArrayIterator { using offset_type = typename Type::offset_type; const ArraySpan& arr; const offset_type* offsets; @@ -372,11 +388,12 @@ struct ArrayIterator { // Iterator over various output array types, taking a GetOutputType -template +template struct OutputArrayWriter; template -struct OutputArrayWriter> { + requires codegen_c_number_or_decimal +struct OutputArrayWriter { using T = typename TypeTraits::ScalarType::ValueType; T* values; @@ -395,11 +412,11 @@ struct OutputArrayWriter> { // (Un)box Scalar to / from C++ value -template +template struct UnboxScalar; -template -struct UnboxScalar> { +template +struct UnboxScalar { using T = typename Type::c_type; static T Unbox(const Scalar& val) { std::string_view view = @@ -417,8 +434,8 @@ struct UnboxScalar { } }; -template -struct UnboxScalar> { +template +struct UnboxScalar { using T = std::string_view; static T Unbox(const Scalar& val) { if (!val.is_valid) return std::string_view(); @@ -462,9 +479,9 @@ struct UnboxScalar { // values, such as Decimal128 rather than std::string_view. template -static typename ::arrow::internal::call_traits::enable_if_return::type -VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func, - NullFunc&& null_func) { + requires codegen_visit_returns_void::T> +static void VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func, + NullFunc&& null_func) { VisitArraySpanInline( arr, [&](typename GetViewType::PhysicalType v) { @@ -474,9 +491,9 @@ VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func, } template -static typename ::arrow::internal::call_traits::enable_if_return::type -VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func, - NullFunc&& null_func) { + requires codegen_visit_returns_status::T> +static Status VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func, + NullFunc&& null_func) { return VisitArraySpanInline( arr, [&](typename GetViewType::PhysicalType v) { @@ -582,11 +599,11 @@ static Status SimpleBinary(KernelContext* ctx, const ExecSpan& batch, ExecResult // of output values to write into output memory. Boolean and primitive outputs // are currently implemented, and the validity bitmap is presumed to be handled // at a higher level, so this writes into every output slot, null or not. -template +template struct OutputAdapter; -template -struct OutputAdapter> { +template +struct OutputAdapter { template static Status Write(KernelContext*, ArraySpan* out, Generator&& generator) { GenerateBitsUnrolled(out->buffers[1].data, out->offset, out->length, @@ -596,7 +613,8 @@ struct OutputAdapter> { }; template -struct OutputAdapter> { + requires codegen_c_number_or_decimal +struct OutputAdapter { using T = std::conditional_t, Float16, typename TypeTraits::ScalarType::ValueType>; @@ -611,8 +629,8 @@ struct OutputAdapter> { } }; -template -struct OutputAdapter> { +template +struct OutputAdapter { template static Status Write(KernelContext* ctx, ArraySpan* out, Generator&& generator) { return Status::NotImplemented("NYI"); @@ -668,7 +686,7 @@ struct ScalarUnaryNotNullStateful { // NOTE: In ArrayExec, Type is really OutputType - template + template struct ArrayExec { static Status Exec(const ThisType& functor, KernelContext* ctx, const ExecSpan& batch, ExecResult* out) { @@ -679,7 +697,11 @@ struct ScalarUnaryNotNullStateful { }; template - struct ArrayExec> { + requires codegen_c_number_or_decimal + struct ArrayExec { + using OutValue = typename GetOutputType::T; + using Arg0Value = typename GetViewType::T; + static Status Exec(const ThisType& functor, KernelContext* ctx, const ArraySpan& arg0, ExecResult* out) { Status st = Status::OK(); @@ -698,7 +720,11 @@ struct ScalarUnaryNotNullStateful { }; template - struct ArrayExec> { + requires arrow_base_binary + struct ArrayExec { + using OutValue = typename GetOutputType::T; + using Arg0Value = typename GetViewType::T; + static Status Exec(const ThisType& functor, KernelContext* ctx, const ArraySpan& arg0, ExecResult* out) { // NOTE: This code is not currently used by any kernels and has @@ -720,7 +746,11 @@ struct ScalarUnaryNotNullStateful { }; template - struct ArrayExec::value>> { + requires arrow_boolean + struct ArrayExec { + using OutValue = typename GetOutputType::T; + using Arg0Value = typename GetViewType::T; + static Status Exec(const ThisType& functor, KernelContext* ctx, const ArraySpan& arg0, ExecResult* out) { Status st = Status::OK(); diff --git a/cpp/src/arrow/compute/kernels/copy_data_internal.h b/cpp/src/arrow/compute/kernels/copy_data_internal.h index 735c2034c3f3..cb53f5027b73 100644 --- a/cpp/src/arrow/compute/kernels/copy_data_internal.h +++ b/cpp/src/arrow/compute/kernels/copy_data_internal.h @@ -23,7 +23,7 @@ namespace arrow { namespace compute { namespace internal { -template +template struct CopyDataUtils {}; template <> @@ -83,8 +83,8 @@ struct CopyDataUtils { }; template -struct CopyDataUtils< - Type, enable_if_t::value || is_interval_type::value>> { + requires(arrow_number || arrow_interval) +struct CopyDataUtils { using CType = typename TypeTraits::CType; static void CopyData(const DataType&, const Scalar& in, const int64_t in_offset, diff --git a/cpp/src/arrow/compute/kernels/hash_aggregate.cc b/cpp/src/arrow/compute/kernels/hash_aggregate.cc index 3ab7ff065b28..909bd1260be9 100644 --- a/cpp/src/arrow/compute/kernels/hash_aggregate.cc +++ b/cpp/src/arrow/compute/kernels/hash_aggregate.cc @@ -328,7 +328,7 @@ struct MinMaxOp { static constexpr CType max(CType a, CType b) { return std::fmax(a, b); } }; -template +template struct GroupedMinMaxImpl final : public GroupedAggregator { using CType = typename TypeTraits::CType; using GetSet = GroupedValueTraits; @@ -434,10 +434,8 @@ struct GroupedMinMaxImpl final : public GroupedAggregator { // For binary-like types // In principle, FixedSizeBinary could use base implementation template -struct GroupedMinMaxImpl::value || - std::is_same::value>> - final : public GroupedAggregator { + requires(arrow_base_binary || std::same_as) +struct GroupedMinMaxImpl final : public GroupedAggregator { using Allocator = arrow::stl::allocator; using StringType = std::basic_string, Allocator>; @@ -526,8 +524,9 @@ struct GroupedMinMaxImpl - enable_if_base_binary MakeOffsetsValues( - ArrayData* array, const std::vector>& values) { + requires arrow_base_binary + Status MakeOffsetsValues(ArrayData* array, + const std::vector>& values) { using offset_type = typename T::offset_type; ARROW_ASSIGN_OR_RAISE( auto raw_offsets, @@ -567,8 +566,9 @@ struct GroupedMinMaxImpl - enable_if_same MakeOffsetsValues( - ArrayData* array, const std::vector>& values) { + requires std::same_as + Status MakeOffsetsValues(ArrayData* array, + const std::vector>& values) { const uint8_t* null_bitmap = array->buffers[0]->data(); const int32_t slot_width = checked_cast(*array->type).byte_width(); @@ -667,8 +667,8 @@ HashAggregateKernel MakeMinOrMaxKernel(HashAggregateFunction* min_max_func) { } struct GroupedMinMaxFactory { - template - enable_if_physical_integer Visit(const T&) { + template + Status Visit(const T&) { using PhysicalType = typename T::PhysicalType; kernel = MakeKernel(std::move(argument_type), MinMaxInit); return Status::OK(); @@ -686,14 +686,14 @@ struct GroupedMinMaxFactory { return Status::OK(); } - template - enable_if_decimal Visit(const T&) { + template + Status Visit(const T&) { kernel = MakeKernel(std::move(argument_type), MinMaxInit); return Status::OK(); } - template - enable_if_base_binary Visit(const T&) { + template + Status Visit(const T&) { kernel = MakeKernel(std::move(argument_type), MinMaxInit); return Status::OK(); } @@ -736,7 +736,7 @@ struct GroupedMinMaxFactory { // ---------------------------------------------------------------------- // FirstLast implementation -template +template struct GroupedFirstLastImpl final : public GroupedAggregator { using CType = typename TypeTraits::CType; using GetSet = GroupedValueTraits; @@ -926,10 +926,8 @@ struct GroupedFirstLastImpl final : public GroupedAggregator { }; template -struct GroupedFirstLastImpl::value || - std::is_same::value>> - final : public GroupedAggregator { + requires(arrow_base_binary || std::same_as) +struct GroupedFirstLastImpl final : public GroupedAggregator { using Allocator = arrow::stl::allocator; using StringType = std::basic_string, Allocator>; @@ -1059,8 +1057,9 @@ struct GroupedFirstLastImpl - enable_if_base_binary MakeOffsetsValues( - ArrayData* array, const std::vector>& values) { + requires arrow_base_binary + Status MakeOffsetsValues(ArrayData* array, + const std::vector>& values) { using offset_type = typename T::offset_type; ARROW_ASSIGN_OR_RAISE( auto raw_offsets, @@ -1100,8 +1099,9 @@ struct GroupedFirstLastImpl - enable_if_same MakeOffsetsValues( - ArrayData* array, const std::vector>& values) { + requires std::same_as + Status MakeOffsetsValues(ArrayData* array, + const std::vector>& values) { const uint8_t* null_bitmap = array->buffers[0]->data(); const int32_t slot_width = checked_cast(*array->type).byte_width(); @@ -1172,8 +1172,8 @@ HashAggregateKernel MakeFirstOrLastKernel(HashAggregateFunction* first_last_func } struct GroupedFirstLastFactory { - template - enable_if_physical_integer Visit(const T&) { + template + Status Visit(const T&) { using PhysicalType = typename T::PhysicalType; kernel = MakeKernel(std::move(argument_type), FirstLastInit, /*ordered*/ true); @@ -1192,8 +1192,8 @@ struct GroupedFirstLastFactory { return Status::OK(); } - template - enable_if_base_binary Visit(const T&) { + template + Status Visit(const T&) { kernel = MakeKernel(std::move(argument_type), FirstLastInit); return Status::OK(); } @@ -1556,7 +1556,7 @@ Result> GroupedDistinctInit(KernelContext* ctx, // ---------------------------------------------------------------------- // One implementation -template +template struct GroupedOneImpl final : public GroupedAggregator { using CType = typename TypeTraits::CType; using GetSet = GroupedValueTraits; @@ -1652,9 +1652,8 @@ struct GroupedNullOneImpl : public GroupedAggregator { }; template -struct GroupedOneImpl::value || - std::is_same::value>> - final : public GroupedAggregator { + requires(arrow_base_binary || std::same_as) +struct GroupedOneImpl final : public GroupedAggregator { using Allocator = arrow::stl::allocator; using StringType = std::basic_string, Allocator>; @@ -1713,8 +1712,9 @@ struct GroupedOneImpl::value || } template - enable_if_base_binary MakeOffsetsValues( - ArrayData* array, const std::vector>& values) { + requires arrow_base_binary + Status MakeOffsetsValues(ArrayData* array, + const std::vector>& values) { using offset_type = typename T::offset_type; ARROW_ASSIGN_OR_RAISE( auto raw_offsets, @@ -1754,8 +1754,9 @@ struct GroupedOneImpl::value || } template - enable_if_same MakeOffsetsValues( - ArrayData* array, const std::vector>& values) { + requires std::same_as + Status MakeOffsetsValues(ArrayData* array, + const std::vector>& values) { const uint8_t* null_bitmap = array->buffers[0]->data(); const int32_t slot_width = checked_cast(*array->type).byte_width(); @@ -1796,27 +1797,27 @@ Result> GroupedOneInit(KernelContext* ctx, } struct GroupedOneFactory { - template - enable_if_physical_integer Visit(const T&) { + template + Status Visit(const T&) { using PhysicalType = typename T::PhysicalType; kernel = MakeKernel(std::move(argument_type), GroupedOneInit); return Status::OK(); } - template - enable_if_floating_point Visit(const T&) { + template + Status Visit(const T&) { kernel = MakeKernel(std::move(argument_type), GroupedOneInit); return Status::OK(); } - template - enable_if_decimal Visit(const T&) { + template + Status Visit(const T&) { kernel = MakeKernel(std::move(argument_type), GroupedOneInit); return Status::OK(); } - template - enable_if_base_binary Visit(const T&) { + template + Status Visit(const T&) { kernel = MakeKernel(std::move(argument_type), GroupedOneInit); return Status::OK(); } @@ -1858,7 +1859,7 @@ struct GroupedOneFactory { // ---------------------------------------------------------------------- // List implementation -template +template struct GroupedListImpl final : public GroupedAggregator { using CType = typename TypeTraits::CType; using GetSet = GroupedValueTraits; @@ -1964,9 +1965,8 @@ struct GroupedListImpl final : public GroupedAggregator { }; template -struct GroupedListImpl::value || - std::is_same::value>> - final : public GroupedAggregator { + requires(arrow_base_binary || std::same_as) +struct GroupedListImpl final : public GroupedAggregator { using Allocator = arrow::stl::allocator; using StringType = std::basic_string, Allocator>; using GetSet = GroupedValueTraits; @@ -2052,8 +2052,9 @@ struct GroupedListImpl::value || } template - enable_if_base_binary MakeOffsetsValues( - ArrayData* array, const std::vector>& values) { + requires arrow_base_binary + Status MakeOffsetsValues(ArrayData* array, + const std::vector>& values) { using offset_type = typename T::offset_type; ARROW_ASSIGN_OR_RAISE( auto raw_offsets, @@ -2093,8 +2094,9 @@ struct GroupedListImpl::value || } template - enable_if_same MakeOffsetsValues( - ArrayData* array, const std::vector>& values) { + requires std::same_as + Status MakeOffsetsValues(ArrayData* array, + const std::vector>& values) { const uint8_t* null_bitmap = array->buffers[0]->data(); const int32_t slot_width = checked_cast(*array->type).byte_width(); @@ -2194,27 +2196,27 @@ Result> GroupedListInit(KernelContext* ctx, } struct GroupedListFactory { - template - enable_if_physical_integer Visit(const T&) { + template + Status Visit(const T&) { using PhysicalType = typename T::PhysicalType; kernel = MakeKernel(std::move(argument_type), GroupedListInit); return Status::OK(); } - template - enable_if_floating_point Visit(const T&) { + template + Status Visit(const T&) { kernel = MakeKernel(std::move(argument_type), GroupedListInit); return Status::OK(); } - template - enable_if_decimal Visit(const T&) { + template + Status Visit(const T&) { kernel = MakeKernel(std::move(argument_type), GroupedListInit); return Status::OK(); } - template - enable_if_base_binary Visit(const T&) { + template + Status Visit(const T&) { kernel = MakeKernel(std::move(argument_type), GroupedListInit); return Status::OK(); } diff --git a/cpp/src/arrow/compute/kernels/hash_aggregate_internal.h b/cpp/src/arrow/compute/kernels/hash_aggregate_internal.h index 9ea4cdfcc5fd..93973f205fa8 100644 --- a/cpp/src/arrow/compute/kernels/hash_aggregate_internal.h +++ b/cpp/src/arrow/compute/kernels/hash_aggregate_internal.h @@ -17,7 +17,9 @@ #pragma once +#include #include +#include #include "arrow/array/data.h" #include "arrow/buffer_builder.h" @@ -150,9 +152,10 @@ struct GroupedValueTraits { }; template -typename arrow::internal::call_traits::enable_if_return::type -VisitGroupedValues(const ExecSpan& batch, ConsumeValue&& valid_func, - ConsumeNull&& null_func) { + requires std::is_void_v< + std::invoke_result_t::CType>> +void VisitGroupedValues(const ExecSpan& batch, ConsumeValue&& valid_func, + ConsumeNull&& null_func) { auto g = batch[1].array.GetValues(1); if (batch[0].is_array()) { VisitArrayValuesInline( @@ -175,9 +178,10 @@ VisitGroupedValues(const ExecSpan& batch, ConsumeValue&& valid_func, } template -typename arrow::internal::call_traits::enable_if_return::type -VisitGroupedValues(const ExecSpan& batch, ConsumeValue&& valid_func, - ConsumeNull&& null_func) { + requires std::same_as< + Status, std::invoke_result_t::T>> +Status VisitGroupedValues(const ExecSpan& batch, ConsumeValue&& valid_func, + ConsumeNull&& null_func) { auto g = batch[1].array.GetValues(1); if (batch[0].is_array()) { return VisitArrayValuesInline( diff --git a/cpp/src/arrow/compute/kernels/hash_aggregate_numeric.cc b/cpp/src/arrow/compute/kernels/hash_aggregate_numeric.cc index aa231430aa06..af1f5112736a 100644 --- a/cpp/src/arrow/compute/kernels/hash_aggregate_numeric.cc +++ b/cpp/src/arrow/compute/kernels/hash_aggregate_numeric.cc @@ -155,14 +155,13 @@ struct GroupedReducingAggregator : public GroupedAggregator { std::shared_ptr out_type() const override { return out_type_; } template - enable_if_t::value, Result>> GetOutType( - const std::shared_ptr& in_type) { + requires(!arrow_decimal) + Result> GetOutType(const std::shared_ptr& in_type) { return TypeTraits::type_singleton(); } - template - enable_if_decimal>> GetOutType( - const std::shared_ptr& in_type) { + template + Result> GetOutType(const std::shared_ptr& in_type) { if (PromoteDecimal()) { return WidenDecimalToMaxPrecision(in_type); } else { @@ -280,9 +279,8 @@ struct GroupedSumImpl : public GroupedReducingAggregator - static enable_if_number Reduce(const DataType&, const CType u, - const InputCType v) { + template + static CType Reduce(const DataType&, const CType u, const InputCType v) { return static_cast(to_unsigned(u) + to_unsigned(static_cast(v))); } @@ -320,9 +318,8 @@ struct GroupedProductImpl final return MultiplyTraits::one(out_type); } - template - static enable_if_number Reduce(const DataType& out_type, const CType u, - const InputCType v) { + template + static CType Reduce(const DataType& out_type, const CType u, const InputCType v) { return MultiplyTraits::Multiply(out_type, u, static_cast(v)); } @@ -369,9 +366,8 @@ struct GroupedMeanImpl static CType NullValue(const DataType&) { return CType(0); } - template - static enable_if_number Reduce(const DataType&, const CType u, - const InputCType v) { + template + static CType Reduce(const DataType&, const CType u, const InputCType v) { return static_cast(u) + static_cast(v); } @@ -379,8 +375,8 @@ struct GroupedMeanImpl return static_cast(to_unsigned(u) + to_unsigned(v)); } - template - static enable_if_decimal> DoMean(CType reduced, int64_t count) { + template + static Result DoMean(CType reduced, int64_t count) { static_assert(std::is_same::value, ""); CType quotient, remainder; ARROW_ASSIGN_OR_RAISE(std::tie(quotient, remainder), reduced.Divide(count)); @@ -397,8 +393,8 @@ struct GroupedMeanImpl } template - static enable_if_t::value, Result> DoMean(CType reduced, - int64_t count) { + requires(!arrow_decimal) + static Result DoMean(CType reduced, int64_t count) { return static_cast(reduced) / count; } @@ -868,14 +864,14 @@ using GroupedKurtosisImpl = template