-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from elbeno/for-each-n-args
For each n args
- Loading branch information
Showing
12 changed files
with
196 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
|
||
== `for_each_n_args.hpp` | ||
|
||
https://github.com/intel/cpp-std-extensions/blob/main/include/stdx/for_each_n_args.hpp[`for_each_n_args.hpp`] | ||
provides a method for calling a function (or other callable) with batches of | ||
arguments from a parameter pack. | ||
|
||
Examples: | ||
[source,cpp] | ||
---- | ||
auto f(int x, int y) -> void { /* do something with x and y */ } | ||
stdx::for_each_n_args(f, 1, 2, 3, 4); // this calls f(1, 2) and f(3, 4) | ||
---- | ||
|
||
The number of arguments passed to `for_each_n_args` must be a multiple of the | ||
argument "batch size" - which by default is the arity of the passed function. | ||
|
||
Sometimes, the passed callable is a generic function where the arity cannot be | ||
automatically determined, or sometimes it may be a function with default | ||
arguments which we want to use. In that case it is possible to override the | ||
default batch size: | ||
[source,cpp] | ||
---- | ||
auto f(auto x, auto y) -> void { /* do something with x and y */ } | ||
stdx::for_each_n_args<2>(f, 1, 2, 3, 4); // this calls f(1, 2) and f(3, 4) | ||
auto g(int x, int y, int z = 42) -> void { /* do something with x, y and z */ } | ||
stdx::for_each_n_args<2>(g, 1, 2, 3, 4); // this calls g(1, 2, 42) and g(3, 4, 42) | ||
---- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#pragma once | ||
|
||
#include <stdx/function_traits.hpp> | ||
|
||
#if __cplusplus >= 202002L | ||
#include <stdx/tuple.hpp> | ||
#define TUPLE_T stdx::tuple | ||
#define TUPLE_GET stdx::get | ||
#else | ||
#include <tuple> | ||
#define TUPLE_T std::tuple | ||
#define TUPLE_GET std::get | ||
#endif | ||
|
||
#include <cstddef> | ||
#include <functional> | ||
#include <utility> | ||
|
||
namespace stdx { | ||
inline namespace v1 { | ||
|
||
namespace detail { | ||
template <typename, typename> struct for_each_n_args; | ||
|
||
template <std::size_t... Rows, std::size_t... Columns> | ||
struct for_each_n_args<std::index_sequence<Rows...>, | ||
std::index_sequence<Columns...>> { | ||
template <typename F, typename T> static auto apply(F &&f, T &&t) -> void { | ||
(exec<Rows * sizeof...(Columns)>(f, std::forward<T>(t)), ...); | ||
} | ||
|
||
private: | ||
template <std::size_t RowIndex, typename F, typename T> | ||
static auto exec(F &&f, T &&t) -> void { | ||
std::invoke(f, TUPLE_GET<RowIndex + Columns>(std::forward<T>(t))...); | ||
} | ||
}; | ||
} // namespace detail | ||
|
||
template <std::size_t N = 0, typename F, typename... Args> | ||
void for_each_n_args(F &&f, Args &&...args) { | ||
constexpr auto batch_size = [] { | ||
if constexpr (N == 0) { | ||
return arity_t<F>::value; | ||
} else { | ||
return N; | ||
} | ||
}(); | ||
static_assert(sizeof...(Args) % batch_size == 0, | ||
"for_each_n_args: number of args must be a multiple of the " | ||
"given N (or function arity)"); | ||
|
||
using tuple_t = TUPLE_T<Args &&...>; | ||
detail::for_each_n_args< | ||
std::make_index_sequence<sizeof...(Args) / batch_size>, | ||
std::make_index_sequence<batch_size>>::apply(std::forward<F>(f), | ||
tuple_t{std::forward<Args>( | ||
args)...}); | ||
} | ||
} // namespace v1 | ||
} // namespace stdx | ||
|
||
#undef TUPLE_T | ||
#undef TUPLE_GET |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#include "detail/tuple_types.hpp" | ||
|
||
#include <stdx/for_each_n_args.hpp> | ||
|
||
#include <catch2/catch_test_macros.hpp> | ||
|
||
TEST_CASE("default to unary function", "[for_each_n_args]") { | ||
auto sum = 0; | ||
auto f = [&](int x) { sum += x; }; | ||
stdx::for_each_n_args(f, 1, 2, 3); | ||
CHECK(sum == 6); | ||
} | ||
|
||
TEST_CASE("binary function", "[for_each_n_args]") { | ||
auto sum = 0; | ||
auto f = [&](int x, int y) { sum += x * y; }; | ||
stdx::for_each_n_args<2>(f, 2, 3, 3, 4); | ||
CHECK(sum == 18); | ||
} | ||
|
||
TEST_CASE("generic function", "[for_each_n_args]") { | ||
auto sum = 0; | ||
auto f = [&](auto x, auto y) { sum += x * y; }; | ||
stdx::for_each_n_args<2>(f, 2, 3, 3, 4); | ||
CHECK(sum == 18); | ||
} | ||
|
||
TEST_CASE("move-only arguments", "[for_each_n_args]") { | ||
auto sum = 0; | ||
auto f = [&](move_only x) { sum += x.value; }; | ||
stdx::for_each_n_args(f, move_only{1}, move_only{2}, move_only{3}); | ||
CHECK(sum == 6); | ||
} | ||
|
||
TEST_CASE("default arguments", "[for_each_n_args]") { | ||
auto sum = 0; | ||
auto f = [&](int x, int y, int z = 42) { sum += x * y + z; }; | ||
stdx::for_each_n_args<2>(f, 2, 3, 3, 4); | ||
CHECK(sum == 42 + 42 + 18); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#include <stdx/type_traits.hpp> | ||
|
||
#include <catch2/catch_test_macros.hpp> | ||
|
||
namespace { | ||
constexpr auto f() -> int { | ||
if (stdx::is_constant_evaluated()) { | ||
return 42; | ||
} else { | ||
return 0; | ||
} | ||
} | ||
} // namespace | ||
|
||
TEST_CASE("constexpr context", "[is_constant_evaluated]") { | ||
constexpr auto n = f(); | ||
CHECK(n == 42); | ||
} | ||
|
||
TEST_CASE("runtime context", "[is_constant_evaluated]") { | ||
auto n = f(); | ||
CHECK(n == 0); | ||
} |