Skip to content

Commit 470146e

Browse files
committed
✨ Add make_array
Problem: - We sometimes need to make arrays from various things, e.g. templates or factory functions. Solution: - Add `make_array`. Note: - Although `std::experimental::make_array` was largely obviated by CTAD, similar behaviour is included here for consistency. viz. `stdx::make_array(1,2,3)`.
1 parent cefe72a commit 470146e

5 files changed

Lines changed: 90 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ target_sources(
4242
include
4343
FILES
4444
include/stdx/algorithm.hpp
45+
include/stdx/array.hpp
4546
include/stdx/atomic.hpp
4647
include/stdx/atomic_bitset.hpp
4748
include/stdx/bit.hpp

docs/intro.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ into headers whose names match the standard.
6767
The following headers are available:
6868

6969
* https://github.com/intel/cpp-std-extensions/blob/main/include/stdx/algorithm.hpp[`algorithm.hpp`]
70+
* https://github.com/intel/cpp-std-extensions/blob/main/include/stdx/array.hpp[`array.hpp`]
7071
* https://github.com/intel/cpp-std-extensions/blob/main/include/stdx/atomic.hpp[`atomic.hpp`]
7172
* https://github.com/intel/cpp-std-extensions/blob/main/include/stdx/atomic_bitset.hpp[`atomic_bitset.hpp`]
7273
* https://github.com/intel/cpp-std-extensions/blob/main/include/stdx/bit.hpp[`bit.hpp`]

include/stdx/array.hpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#pragma once
2+
3+
#include <array>
4+
#include <type_traits>
5+
#include <utility>
6+
7+
namespace stdx {
8+
inline namespace v1 {
9+
10+
template <typename D = void, typename... Ts>
11+
constexpr auto make_array(Ts &&...ts) {
12+
if constexpr (not std::is_void_v<D>) {
13+
return std::array<D, sizeof...(Ts)>{std::forward<Ts>(ts)...};
14+
} else {
15+
using A = std::common_type_t<Ts...>;
16+
return std::array<A, sizeof...(Ts)>{std::forward<Ts>(ts)...};
17+
}
18+
}
19+
20+
template <template <auto> typename D, typename T, T... Is>
21+
constexpr auto make_array(std::integer_sequence<T, Is...>) {
22+
using A = std::common_type_t<decltype(D<Is>::value)...>;
23+
return std::array<A, sizeof...(Is)>{D<Is>::value...};
24+
}
25+
26+
template <template <auto> typename D, auto N> constexpr auto make_array() {
27+
return make_array<D>(std::make_integer_sequence<decltype(N), N>{});
28+
}
29+
30+
template <typename T, T... Is, typename F>
31+
constexpr auto make_array(std::integer_sequence<T, Is...>, F &&f) {
32+
using A = std::common_type_t<decltype(f.template operator()<Is>())...>;
33+
return std::array<A, sizeof...(Is)>{f.template operator()<Is>()...};
34+
}
35+
36+
template <auto N, typename F> constexpr auto make_array(F &&f) {
37+
return make_array(std::make_integer_sequence<decltype(N), N>{},
38+
std::forward<F>(f));
39+
}
40+
41+
} // namespace v1
42+
} // namespace stdx

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ add_tests(
2121
FILES
2222
algorithm
2323
always_false
24+
array
2425
atomic
2526
atomic_override
2627
atomic_bitset

test/array.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include <stdx/array.hpp>
2+
3+
#include <catch2/catch_test_macros.hpp>
4+
5+
#include <array>
6+
7+
TEST_CASE("make_array (variadic arguments)", "[array]") {
8+
auto arr = stdx::make_array(1, 2, 3, 4, 5);
9+
STATIC_CHECK(std::is_same_v<decltype(arr), std::array<int, 5>>);
10+
CHECK(arr == std::array{1, 2, 3, 4, 5});
11+
}
12+
13+
namespace {
14+
template <auto I> using V = std::integral_constant<decltype(I), I + 1>;
15+
}
16+
17+
TEST_CASE("make_array by sequence (template with ::value)", "[array]") {
18+
auto arr = stdx::make_array<V>(std::make_integer_sequence<int, 5>{});
19+
STATIC_CHECK(std::is_same_v<decltype(arr), std::array<int, 5>>);
20+
CHECK(arr == std::array{1, 2, 3, 4, 5});
21+
}
22+
23+
TEST_CASE("make_array by extent (template with ::value)", "[array]") {
24+
auto arr = stdx::make_array<V, 5>();
25+
STATIC_CHECK(std::is_same_v<decltype(arr), std::array<int, 5>>);
26+
CHECK(arr == std::array{1, 2, 3, 4, 5});
27+
}
28+
29+
namespace {
30+
struct {
31+
template <auto I> auto operator()() { return I + 1; }
32+
} f;
33+
} // namespace
34+
35+
TEST_CASE("make_array by sequence (factory function template)", "[array]") {
36+
auto arr = stdx::make_array(std::make_integer_sequence<int, 5>{}, f);
37+
STATIC_CHECK(std::is_same_v<decltype(arr), std::array<int, 5>>);
38+
CHECK(arr == std::array{1, 2, 3, 4, 5});
39+
}
40+
41+
TEST_CASE("make_array by extent (factory function template)", "[array]") {
42+
auto arr = stdx::make_array<5>(f);
43+
STATIC_CHECK(std::is_same_v<decltype(arr), std::array<int, 5>>);
44+
CHECK(arr == std::array{1, 2, 3, 4, 5});
45+
}

0 commit comments

Comments
 (0)