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
20 changes: 20 additions & 0 deletions include/stdx/ct_string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,5 +182,25 @@ template <ct_string S> consteval auto operator""_cts() { return S; }
template <ct_string S> consteval auto operator""_ctst() { return cts_t<S>{}; }
} // namespace ct_string_literals
} // namespace literals

template <ct_string Name> struct with_name {
constexpr static auto name = Name;
friend constexpr auto operator==(with_name, with_name) -> bool = default;
};

namespace detail {
template <typename T>
concept is_ct_string =
stdx::is_value_specialization_of_v<std::remove_cvref_t<T>, ct_string>;
}

template <typename T>
concept named = requires {
{ T::name } -> detail::is_ct_string;
};

template <named T> constexpr auto name_of_v = T::name;
template <named T> using constant_name_of_t = cts_t<T::name>;
template <named T> constexpr auto constant_name_of_v = constant_name_of_t<T>{};
} // namespace v1
} // namespace stdx
8 changes: 8 additions & 0 deletions test/ct_string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,11 @@ TEST_CASE("CT_WRAP", "[ct_string]") {
STATIC_REQUIRE(CT_WRAP(X) == "hello"_ctst);
}.template operator()<"hello">();
}

TEST_CASE("named object", "[ct_string]") {
using namespace stdx::ct_string_literals;
using T = stdx::with_name<"test">;
STATIC_CHECK(stdx::named<T>);
STATIC_CHECK(stdx::name_of_v<T> == "test"_cts);
STATIC_CHECK(stdx::constant_name_of_v<T> == "test"_ctst);
}
26 changes: 11 additions & 15 deletions test/tuple_algorithms.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "detail/tuple_types.hpp"

#include <stdx/ct_string.hpp>
#include <stdx/span.hpp>
#include <stdx/tuple_algorithms.hpp>
#include <stdx/utility.hpp>
Expand Down Expand Up @@ -979,31 +980,26 @@ TEST_CASE("gather with move only types", "[tuple_algorithms]") {
}

namespace {
template <typename T> struct named_int {
using name_t = T;
template <stdx::ct_string Name> struct named_int : stdx::with_name<Name> {
constexpr named_int(int v) : value{v} {}
int value;
friend constexpr auto operator==(named_int, named_int) -> bool = default;
};

template <typename T> using name_of_t = typename T::name_t;
} // namespace

TEST_CASE("gather_by with projection", "[tuple_algorithms]") {
struct A;
struct B;
struct C;
constexpr auto t = stdx::tuple{named_int<C>{3}, named_int<B>{11},
named_int<A>{0}, named_int<B>{12}};
constexpr auto gathered = stdx::gather_by<name_of_t>(t);
constexpr auto t = stdx::tuple{named_int<"C">{3}, named_int<"B">{11},
named_int<"A">{0}, named_int<"B">{12}};
constexpr auto gathered = stdx::gather_by<stdx::constant_name_of_t>(t);
STATIC_REQUIRE(
std::is_same_v<decltype(gathered),
stdx::tuple<stdx::tuple<named_int<A>>,
stdx::tuple<named_int<B>, named_int<B>>,
stdx::tuple<named_int<C>>> const>);
CHECK(get<0>(gathered) == stdx::tuple{named_int<A>{0}});
stdx::tuple<stdx::tuple<named_int<"A">>,
stdx::tuple<named_int<"B">, named_int<"B">>,
stdx::tuple<named_int<"C">>> const>);
CHECK(get<0>(gathered) == stdx::tuple{named_int<"A">{0}});
CHECK(stdx::get<1>(gathered).fold_left(
0, [](auto x, auto y) { return x + y.value; }) == 23);
CHECK(get<2>(gathered) == stdx::tuple{named_int<C>{3}});
CHECK(get<2>(gathered) == stdx::tuple{named_int<"C">{3}});
}

TEST_CASE("tuple_cons", "[tuple_algorithms]") {
Expand Down