Skip to content

Commit 7c4cfea

Browse files
committed
Type/Mapping
1 parent 43be025 commit 7c4cfea

2 files changed

Lines changed: 119 additions & 37 deletions

File tree

modules/Type/Mapping.mpp

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,64 @@
11
export module CppUtils.Type.Mapping;
22

3+
import std;
4+
35
export namespace CppUtils::Type
46
{
5-
template<auto Lhs, auto Rhs>
7+
template<auto Lhs, auto... Rhs>
68
struct Pair final
79
{
810
static constexpr auto lhs = Lhs;
9-
static constexpr auto rhs = Rhs;
11+
static constexpr auto rhs = std::tuple{Rhs...};
1012
};
1113

1214
template<class... Pairs>
1315
struct Mapping final
1416
{
1517
static_assert(sizeof...(Pairs) > 0);
18+
using Values = std::tuple<Pairs...>;
19+
1620
Mapping() = delete;
1721

1822
template<auto Lhs>
19-
[[nodiscard]] static inline consteval auto toRhs() noexcept
23+
[[nodiscard]] static inline consteval auto toRhs() noexcept -> auto
2024
{
21-
return toRhsImpl<Lhs, Pairs...>();
25+
return []<auto Target, class First, class... Rest>(this auto&& self) consteval {
26+
if constexpr (First::lhs == Target)
27+
return First::rhs;
28+
else if constexpr (sizeof...(Rest) == 0)
29+
static_assert([] { return false; }(), "Lhs not found");
30+
else
31+
return self.template operator()<Target, Rest...>();
32+
}.template operator()<Lhs, Pairs...>();
2233
}
2334

2435
template<auto Rhs>
25-
[[nodiscard]] static inline consteval auto toLhs() noexcept
26-
{
27-
return toLhsImpl<Rhs, Pairs...>();
28-
}
29-
30-
private:
31-
template<auto Lhs, class First, class... Rest>
32-
[[nodiscard]] static inline consteval auto toRhsImpl() noexcept
36+
[[nodiscard]] static inline consteval auto toLhs() noexcept -> auto
3337
{
34-
if constexpr (First::lhs == Lhs)
35-
return First::rhs;
36-
else
37-
return toRhsImpl<Lhs, Rest...>();
38+
return []<auto Target, class First, class... Rest>(this auto&& self) consteval {
39+
if constexpr (contains<Target>(First::rhs))
40+
return First::lhs;
41+
else if constexpr (sizeof...(Rest) == 0)
42+
static_assert([] { return false; }(), "Rhs not found");
43+
else
44+
return self.template operator()<Target, Rest...>();
45+
}.template operator()<Rhs, Pairs...>();
3846
}
3947

40-
template<auto>
41-
[[nodiscard]] static inline consteval auto toRhsImpl() noexcept
42-
{
43-
static_assert([] { return false; }(), "Lhs not found");
44-
}
45-
46-
template<auto Rhs, class First, class... Rest>
47-
[[nodiscard]] static inline consteval auto toLhsImpl() noexcept
48+
template<auto Lhs>
49+
[[nodiscard]] static inline consteval auto toSingleRhs() noexcept -> auto
4850
{
49-
if constexpr (First::rhs == Rhs)
50-
return First::lhs;
51-
else
52-
return toLhsImpl<Rhs, Rest...>();
51+
constexpr auto tuple = toRhs<Lhs>();
52+
static_assert(std::tuple_size_v<decltype(tuple)> == 1);
53+
return std::get<0>(tuple);
5354
}
5455

55-
template<auto>
56-
[[nodiscard]] static inline consteval auto toLhsImpl() noexcept
56+
template<auto Value, class Tuple>
57+
[[nodiscard]] static inline consteval auto contains(const Tuple& tuple) noexcept -> bool
5758
{
58-
static_assert([] { return false; }(), "Rhs not found");
59+
return []<std::size_t... I>(const Tuple& tuple, std::index_sequence<I...>) constexpr noexcept -> bool {
60+
return ((std::get<I>(tuple) == Value) or ...);
61+
}(tuple, std::make_index_sequence<std::tuple_size_v<Tuple>>{});
5962
}
6063
};
6164
}

tests/Type/Mapping.mpp

Lines changed: 85 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,90 @@ import CppUtils;
44

55
namespace CppUtils::UnitTest::Type::Mapping
66
{
7-
using Map = ::CppUtils::Type::Mapping<
8-
::CppUtils::Type::Pair<0, 100>,
9-
::CppUtils::Type::Pair<1, 200>,
10-
::CppUtils::Type::Pair<2, 300>>;
7+
namespace Map
8+
{
9+
using Map = ::CppUtils::Type::Mapping<
10+
::CppUtils::Type::Pair<0, 100>,
11+
::CppUtils::Type::Pair<1, 200>,
12+
::CppUtils::Type::Pair<2, 300>>;
1113

12-
static_assert(Map::toRhs<1>() == 200);
13-
static_assert(Map::toLhs<300>() == 2);
14+
static_assert(std::get<0>(Map::toRhs<0>()) == 100);
15+
static_assert(std::get<0>(Map::toRhs<1>()) == 200);
16+
static_assert(std::get<0>(Map::toRhs<2>()) == 300);
17+
18+
static_assert(Map::toSingleRhs<0>() == 100);
19+
static_assert(Map::toSingleRhs<1>() == 200);
20+
static_assert(Map::toSingleRhs<2>() == 300);
21+
22+
static_assert(Map::toLhs<100>() == 0);
23+
static_assert(Map::toLhs<200>() == 1);
24+
static_assert(Map::toLhs<300>() == 2);
25+
26+
static_assert(Map::contains<100>(Map::toRhs<0>()));
27+
static_assert(Map::contains<200>(Map::toRhs<1>()));
28+
static_assert(not Map::contains<1'000>(Map::toRhs<2>()));
29+
}
30+
31+
namespace MultiMap
32+
{
33+
using MultiMap = ::CppUtils::Type::Mapping<
34+
::CppUtils::Type::Pair<0, 1, 2, 3>>;
35+
36+
static_assert(std::tuple_size_v<decltype(MultiMap::toRhs<0>())> == 3);
37+
static_assert(std::get<0>(MultiMap::toRhs<0>()) == 1);
38+
static_assert(std::get<1>(MultiMap::toRhs<0>()) == 2);
39+
static_assert(std::get<2>(MultiMap::toRhs<0>()) == 3);
40+
41+
static_assert(MultiMap::toLhs<1>() == 0);
42+
static_assert(MultiMap::toLhs<2>() == 0);
43+
static_assert(MultiMap::toLhs<3>() == 0);
44+
45+
static_assert(MultiMap::contains<1>(MultiMap::toRhs<0>()));
46+
static_assert(MultiMap::contains<2>(MultiMap::toRhs<0>()));
47+
static_assert(not MultiMap::contains<10>(MultiMap::toRhs<0>()));
48+
}
49+
50+
namespace Boolean
51+
{
52+
using BooleanMap = ::CppUtils::Type::Mapping<
53+
::CppUtils::Type::Pair<0, true>,
54+
::CppUtils::Type::Pair<1, false>>;
55+
56+
static_assert(BooleanMap::toSingleRhs<0>());
57+
static_assert(not BooleanMap::toSingleRhs<1>());
58+
59+
static_assert(BooleanMap::contains<true>(BooleanMap::toRhs<0>()));
60+
static_assert(BooleanMap::contains<false>(BooleanMap::toRhs<1>()));
61+
static_assert(not BooleanMap::contains<true>(BooleanMap::toRhs<1>()));
62+
}
63+
64+
namespace FunctionPointer
65+
{
66+
constexpr auto function(int x) -> int
67+
{
68+
return x * 2;
69+
}
70+
71+
using FunctionMap = ::CppUtils::Type::Mapping<
72+
::CppUtils::Type::Pair<0, &function>>;
73+
74+
static_assert(FunctionMap::toSingleRhs<0>() == &function);
75+
76+
static_assert(FunctionMap::contains<&function>(FunctionMap::toRhs<0>()));
77+
}
78+
79+
namespace MemberFunctionPointer
80+
{
81+
struct Struct final
82+
{
83+
int value;
84+
};
85+
86+
using MemberMap = ::CppUtils::Type::Mapping<
87+
::CppUtils::Type::Pair<0, &Struct::value>>;
88+
89+
static_assert(MemberMap::toSingleRhs<0>() == &Struct::value);
90+
91+
static_assert(MemberMap::contains<&Struct::value>(MemberMap::toRhs<0>()));
92+
}
1493
}

0 commit comments

Comments
 (0)