diff --git a/cth/incl/cth/data/cxpr.hpp b/cth/incl/cth/data/cxpr.hpp new file mode 100644 index 0000000..3345768 --- /dev/null +++ b/cth/incl/cth/data/cxpr.hpp @@ -0,0 +1,24 @@ +#pragma once +#include +#include +#include +#include + +namespace cth::dt { + +/** + * copies the range returned by a constexpr generator into a std::array + * @details allows results computed with constexpr std::vector & co. to outlive constant evaluation + * @tparam Generator callable without arguments that returns a sized range + */ +template +[[nodiscard]] consteval auto as_cxpr_array() { + using value_type = std::ranges::range_value_t; + constexpr size_t SIZE = std::ranges::size(Generator()); + + std::array result{}; + std::ranges::copy(Generator(), result.begin()); + return result; +} + +} diff --git a/cth/tests/src/data/cxpr_test.cpp b/cth/tests/src/data/cxpr_test.cpp new file mode 100644 index 0000000..649b1cf --- /dev/null +++ b/cth/tests/src/data/cxpr_test.cpp @@ -0,0 +1,31 @@ +#include "test.hpp" + +#include "cth/data/cxpr.hpp" + +#include +#include + +namespace cth::dt { + +DATA_TEST(as_cxpr_array, main) { + constexpr auto array = as_cxpr_array<[] { return std::vector{1, 2, 3}; }>(); + + static_assert(array.size() == 3); + EXPECT_EQ(array, (std::array{1, 2, 3})); +} + +DATA_TEST(as_cxpr_array, computed_size) { + static constexpr std::string_view CSV = "a,bb,ccc"; + + constexpr auto splits = as_cxpr_array<[] { + std::vector result{}; + for(size_t i = 0; i < CSV.size(); i++) + if(CSV[i] == ',') + result.push_back(i); + return result; + }>(); + + EXPECT_EQ(splits, (std::array{1, 4})); +} + +}