Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions cpp/src/arrow/compute/kernels/codegen_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <optional>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>

Expand Down Expand Up @@ -479,9 +480,9 @@ struct UnboxScalar<Decimal256Type> {
// values, such as Decimal128 rather than std::string_view.

template <typename T, typename VisitFunc, typename NullFunc>
static typename ::arrow::internal::call_traits::enable_if_return<VisitFunc, void>::type
VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func,
NullFunc&& null_func) {
requires std::is_void_v<std::invoke_result_t<VisitFunc, typename GetViewType<T>::T>>
static void VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func,
NullFunc&& null_func) {
VisitArraySpanInline<T>(
arr,
[&](typename GetViewType<T>::PhysicalType v) {
Expand All @@ -491,9 +492,10 @@ VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func,
}

template <typename T, typename VisitFunc, typename NullFunc>
static typename ::arrow::internal::call_traits::enable_if_return<VisitFunc, Status>::type
VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func,
NullFunc&& null_func) {
requires std::is_same_v<std::invoke_result_t<VisitFunc, typename GetViewType<T>::T>,
Status>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we may be able to use std::is_invocable_r_v here. It might also work for cases where the return type is void. It depends on how strict we want the constraints to be.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And FYI, C++20 provides std::same_as to replace std::is_same_v.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And FYI, C++20 provides std::same_as to replace std::is_same_v.

Ah, nice! I added #50720 for this change, as this is not widely used in the code-base for now.

I think we may be able to use std::is_invocable_r_v here. It might also work for cases where the return type is void. It depends on how strict we want the constraints to be.

I am not sure whether I find the std::is_invocable_r_v more readable in this codebase, compared to using more well-known constructs?

static Status VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func,
NullFunc&& null_func) {
return VisitArraySpanInline<T>(
arr,
[&](typename GetViewType<T>::PhysicalType v) {
Expand Down
15 changes: 9 additions & 6 deletions cpp/src/arrow/compute/kernels/hash_aggregate_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#pragma once

#include <memory>
#include <type_traits>

#include "arrow/array/data.h"
#include "arrow/buffer_builder.h"
Expand Down Expand Up @@ -149,9 +150,10 @@ struct GroupedValueTraits<BooleanType> {
};

template <typename Type, typename ConsumeValue, typename ConsumeNull>
typename arrow::internal::call_traits::enable_if_return<ConsumeValue, void>::type
VisitGroupedValues(const ExecSpan& batch, ConsumeValue&& valid_func,
ConsumeNull&& null_func) {
requires std::is_void_v<
std::invoke_result_t<ConsumeValue, uint32_t, typename GetViewType<Type>::T>>
void VisitGroupedValues(const ExecSpan& batch, ConsumeValue&& valid_func,
ConsumeNull&& null_func) {
auto g = batch[1].array.GetValues<uint32_t>(1);
if (batch[0].is_array()) {
VisitArrayValuesInline<Type>(
Expand All @@ -174,9 +176,10 @@ VisitGroupedValues(const ExecSpan& batch, ConsumeValue&& valid_func,
}

template <typename Type, typename ConsumeValue, typename ConsumeNull>
typename arrow::internal::call_traits::enable_if_return<ConsumeValue, Status>::type
VisitGroupedValues(const ExecSpan& batch, ConsumeValue&& valid_func,
ConsumeNull&& null_func) {
requires std::is_same_v<
std::invoke_result_t<ConsumeValue, uint32_t, typename GetViewType<Type>::T>, Status>
Status VisitGroupedValues(const ExecSpan& batch, ConsumeValue&& valid_func,
ConsumeNull&& null_func) {
auto g = batch[1].array.GetValues<uint32_t>(1);
if (batch[0].is_array()) {
return VisitArrayValuesInline<Type>(
Expand Down
5 changes: 2 additions & 3 deletions cpp/src/arrow/util/cache_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,8 @@ struct ThreadUnsafeMemoizer {
};

template <template <typename...> class Cache, template <typename...> class MemoizerType,
typename Func,
typename Key = typename std::decay<call_traits::argument_type<0, Func>>::type,
typename Value = typename std::decay<call_traits::return_type<Func>>::type,
typename Func, typename Key = std::decay_t<call_traits::argument_type<0, Func>>,
typename Value = std::decay_t<std::invoke_result_t<Func, const Key&>>,
typename Memoizer = MemoizerType<Key, Value, Cache<Key, Value>, Func>,
typename RetType = typename Memoizer::RetType>
static std::function<RetType(const Key&)> Memoize(Func&& func, int32_t cache_capacity) {
Expand Down
43 changes: 0 additions & 43 deletions cpp/src/arrow/util/functional.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,6 @@ struct Empty {
/// TODO(ARROW-12655) support function pointers
struct call_traits {
public:
template <typename R, typename... A>
static std::false_type is_overloaded_impl(R(A...));

template <typename F>
static std::false_type is_overloaded_impl(decltype(&F::operator())*);

template <typename F>
static std::true_type is_overloaded_impl(...);

template <typename F, typename R, typename... A>
static R return_type_impl(R (F::*)(A...));

template <typename F, typename R, typename... A>
static R return_type_impl(R (F::*)(A...) const);

template <std::size_t I, typename F, typename R, typename... A>
static typename std::tuple_element<I, std::tuple<A...>>::type argument_type_impl(
R (F::*)(A...));
Expand All @@ -77,41 +62,13 @@ struct call_traits {
template <typename F, typename R, typename... A>
static std::integral_constant<int, sizeof...(A)> argument_count_impl(R (F::*)(A...) &&);

/// bool constant indicating whether F is a callable with more than one possible
/// signature. Will be true_type for objects which define multiple operator() or which
/// define a template operator()
template <typename F>
using is_overloaded =
decltype(is_overloaded_impl<typename std::decay<F>::type>(NULLPTR));

template <typename F, typename T = void>
using enable_if_overloaded = typename std::enable_if<is_overloaded<F>::value, T>::type;

template <typename F, typename T = void>
using disable_if_overloaded =
typename std::enable_if<!is_overloaded<F>::value, T>::type;

/// If F is not overloaded, the argument types of its call operator can be
/// extracted via call_traits::argument_type<Index, F>
template <std::size_t I, typename F>
using argument_type = decltype(argument_type_impl<I>(&std::decay<F>::type::operator()));

template <typename F>
using argument_count = decltype(argument_count_impl(&std::decay<F>::type::operator()));

template <typename F>
using return_type = decltype(return_type_impl(&std::decay<F>::type::operator()));

template <typename F, typename T, typename RT = T>
using enable_if_return =
typename std::enable_if<std::is_same<return_type<F>, T>::value, RT>;

template <typename T, typename R = void>
using enable_if_empty = typename std::enable_if<std::is_same<T, Empty>::value, R>::type;

template <typename T, typename R = void>
using enable_if_not_empty =
typename std::enable_if<!std::is_same<T, Empty>::value, R>::type;
};

/// A type erased callable object which may only be invoked once.
Expand Down
21 changes: 8 additions & 13 deletions cpp/src/arrow/util/iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include "arrow/result.h"
#include "arrow/status.h"
#include "arrow/util/compare.h"
#include "arrow/util/functional.h"
#include "arrow/util/macros.h"
#include "arrow/util/type_fwd.h"
#include "arrow/util/visibility.h"
Expand Down Expand Up @@ -364,8 +363,7 @@ class FunctionIterator {
};

/// \brief Construct an Iterator which invokes a callable on Next()
template <typename Fn,
typename Ret = typename internal::call_traits::return_type<Fn>::ValueType>
template <typename Fn, typename Ret = typename std::invoke_result_t<Fn&>::ValueType>
Iterator<Ret> MakeFunctionIterator(Fn fn) {
return Iterator<Ret>(FunctionIterator<Fn, Ret>(std::move(fn)));
}
Expand Down Expand Up @@ -455,15 +453,14 @@ class MapIterator {

/// \brief MapIterator takes ownership of an iterator and a function to apply
/// on every element. The mapped function is not allowed to fail.
template <typename Fn, typename From = internal::call_traits::argument_type<0, Fn>,
typename To = internal::call_traits::return_type<Fn>>
template <typename Fn, typename From, typename To = std::invoke_result_t<Fn&, From>>
Iterator<To> MakeMapIterator(Fn map, Iterator<From> it) {
return Iterator<To>(MapIterator<Fn, From, To>(std::move(map), std::move(it)));
}

/// \brief Like MapIterator, but where the function can fail.
template <typename Fn, typename From = internal::call_traits::argument_type<0, Fn>,
typename To = typename internal::call_traits::return_type<Fn>::ValueType>
template <typename Fn, typename From,
typename To = typename std::invoke_result_t<Fn&, From>::ValueType>
Iterator<To> MakeMaybeMapIterator(Fn map, Iterator<From> it) {
return Iterator<To>(MapIterator<Fn, From, To>(std::move(map), std::move(it)));
}
Expand Down Expand Up @@ -520,12 +517,10 @@ struct FilterIterator {
};

/// \brief Like MapIterator, but where the function can fail or reject elements.
template <
typename Fn, typename From = typename internal::call_traits::argument_type<0, Fn>,
typename Ret = typename internal::call_traits::return_type<Fn>::ValueType,
typename To = typename std::tuple_element<0, Ret>::type,
typename Enable = typename std::enable_if<std::is_same<
typename std::tuple_element<1, Ret>::type, FilterIterator::Action>::value>::type>
template <typename Fn, typename From,
typename Ret = typename std::invoke_result_t<Fn&, From>::ValueType,
typename To = std::tuple_element_t<0, Ret>>
requires std::is_same_v<std::tuple_element_t<1, Ret>, FilterIterator::Action>
Iterator<To> MakeFilterIterator(Fn filter, Iterator<From> it) {
return Iterator<To>(
FilterIterator::Impl<Fn, From, To>(std::move(filter), std::move(it)));
Expand Down
6 changes: 3 additions & 3 deletions cpp/src/arrow/util/parallel.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@

#pragma once

#include <type_traits>
#include <utility>
#include <vector>

#include "arrow/status.h"
#include "arrow/util/functional.h"
#include "arrow/util/thread_pool.h"
#include "arrow/util/vector.h"

Expand All @@ -47,7 +47,7 @@ Status ParallelFor(int num_tasks, FUNCTION&& func,
}

template <class FUNCTION, typename T,
typename R = typename internal::call_traits::return_type<FUNCTION>::ValueType>
typename R = typename std::invoke_result_t<FUNCTION, int, T>::ValueType>
Future<std::vector<R>> ParallelForAsync(std::vector<T> inputs, FUNCTION&& func,
Executor* executor = internal::GetCpuThreadPool(),
TaskHints hints = TaskHints{}) {
Expand Down Expand Up @@ -84,7 +84,7 @@ Status OptionalParallelFor(bool use_threads, int num_tasks, FUNCTION&& func,
// depending on the input boolean.

template <class FUNCTION, typename T,
typename R = typename internal::call_traits::return_type<FUNCTION>::ValueType>
typename R = typename std::invoke_result_t<FUNCTION, int, T>::ValueType>
Future<std::vector<R>> OptionalParallelForAsync(
bool use_threads, std::vector<T> inputs, FUNCTION&& func,
Executor* executor = internal::GetCpuThreadPool(), TaskHints hints = TaskHints{}) {
Expand Down
10 changes: 5 additions & 5 deletions cpp/src/arrow/util/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
#pragma once

#include <algorithm>
#include <type_traits>
#include <utility>
#include <vector>

#include "arrow/result.h"
#include "arrow/util/algorithm.h"
#include "arrow/util/functional.h"
#include "arrow/util/logging.h"

namespace arrow {
Expand Down Expand Up @@ -106,8 +106,8 @@ std::vector<To> MapVector(Fn&& map, std::vector<From>&& source) {
}

/// \brief Like MapVector, but where the function can fail.
template <typename Fn, typename From = internal::call_traits::argument_type<0, Fn>,
typename To = typename internal::call_traits::return_type<Fn>::ValueType>
template <typename Fn, typename From,
typename To = typename std::invoke_result_t<Fn, From>::ValueType>
Result<std::vector<To>> MaybeMapVector(Fn&& map, const std::vector<From>& source) {
std::vector<To> out;
out.reserve(source.size());
Expand All @@ -116,8 +116,8 @@ Result<std::vector<To>> MaybeMapVector(Fn&& map, const std::vector<From>& source
return out;
}

template <typename Fn, typename From = internal::call_traits::argument_type<0, Fn>,
typename To = typename internal::call_traits::return_type<Fn>::ValueType>
template <typename Fn, typename From,
typename To = typename std::invoke_result_t<Fn, From>::ValueType>
Result<std::vector<To>> MaybeMapVector(Fn&& map, std::vector<From>&& source) {
std::vector<To> out;
out.reserve(source.size());
Expand Down
32 changes: 19 additions & 13 deletions cpp/src/arrow/visit_data_inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#pragma once

#include <string_view>
#include <type_traits>

#include "arrow/array.h"
#include "arrow/status.h"
Expand All @@ -27,7 +28,6 @@
#include "arrow/util/bit_block_counter.h"
#include "arrow/util/bit_util.h"
#include "arrow/util/checked_cast.h"
#include "arrow/util/functional.h"

namespace arrow {
namespace internal {
Expand Down Expand Up @@ -227,15 +227,21 @@ struct ArraySpanInlineVisitor<T, enable_if_fixed_size_binary<T>> {
} // namespace internal

template <typename T, typename ValidFunc, typename NullFunc>
typename internal::call_traits::enable_if_return<ValidFunc, Status>::type
VisitArraySpanInline(const ArraySpan& arr, ValidFunc&& valid_func, NullFunc&& null_func) {
requires std::is_same_v<
std::invoke_result_t<ValidFunc,
typename internal::ArraySpanInlineVisitor<T>::c_type>,
Status>
Status VisitArraySpanInline(const ArraySpan& arr, ValidFunc&& valid_func,
NullFunc&& null_func) {
return internal::ArraySpanInlineVisitor<T>::VisitStatus(
arr, std::forward<ValidFunc>(valid_func), std::forward<NullFunc>(null_func));
}

template <typename T, typename ValidFunc, typename NullFunc>
typename internal::call_traits::enable_if_return<ValidFunc, void>::type
VisitArraySpanInline(const ArraySpan& arr, ValidFunc&& valid_func, NullFunc&& null_func) {
requires std::is_void_v<std::invoke_result_t<
ValidFunc, typename internal::ArraySpanInlineVisitor<T>::c_type>>
void VisitArraySpanInline(const ArraySpan& arr, ValidFunc&& valid_func,
NullFunc&& null_func) {
return internal::ArraySpanInlineVisitor<T>::VisitVoid(
arr, std::forward<ValidFunc>(valid_func), std::forward<NullFunc>(null_func));
}
Expand Down Expand Up @@ -274,10 +280,10 @@ struct ArraySpanVisitor {
// The `NullFunc` should have the same return type as `ValidFunc`.

template <typename ValidFunc, typename NullFunc>
typename internal::call_traits::enable_if_return<ValidFunc, Status>::type
VisitNullBitmapInline(const uint8_t* valid_bits, int64_t valid_bits_offset,
int64_t num_values, int64_t null_count, ValidFunc&& valid_func,
NullFunc&& null_func) {
requires std::is_same_v<std::invoke_result_t<ValidFunc>, Status>
Status VisitNullBitmapInline(const uint8_t* valid_bits, int64_t valid_bits_offset,
int64_t num_values, int64_t null_count,
ValidFunc&& valid_func, NullFunc&& null_func) {
internal::OptionalBitBlockCounter bit_counter(null_count == 0 ? NULLPTR : valid_bits,
valid_bits_offset, num_values);
int64_t position = 0;
Expand Down Expand Up @@ -306,10 +312,10 @@ VisitNullBitmapInline(const uint8_t* valid_bits, int64_t valid_bits_offset,
}

template <typename ValidFunc, typename NullFunc>
typename internal::call_traits::enable_if_return<ValidFunc, void>::type
VisitNullBitmapInline(const uint8_t* valid_bits, int64_t valid_bits_offset,
int64_t num_values, int64_t null_count, ValidFunc&& valid_func,
NullFunc&& null_func) {
requires std::is_void_v<std::invoke_result_t<ValidFunc>>
void VisitNullBitmapInline(const uint8_t* valid_bits, int64_t valid_bits_offset,
int64_t num_values, int64_t null_count, ValidFunc&& valid_func,
NullFunc&& null_func) {
internal::OptionalBitBlockCounter bit_counter(null_count == 0 ? NULLPTR : valid_bits,
valid_bits_offset, num_values);
int64_t position = 0;
Expand Down
Loading