Nix 2.93.3
Lix: A modern, delicious implementation of the Nix package manager; unstable internal interfaces
Loading...
Searching...
No Matches
charptr-cast.hh
1#pragma once
3
4#include <concepts> // IWYU pragma: keep
5#include <type_traits>
6
7namespace nix {
8
9namespace charptr_cast_detail {
10
12template<typename T>
14{
15 using type = T;
16};
17
18template <typename T>
20{
21 using type = T *;
22};
23
24template <typename T, std::size_t N>
26{
27 using type = T *;
28};
29
30template <typename T>
31using DecayArray = DecayArrayInternal<T>::type;
32
34template<typename T>
35concept IsChar = std::same_as<T, char> || std::same_as<T, unsigned char>;
36
37template<typename T>
38concept IsConvertibleToChar = std::same_as<T, char8_t> || std::same_as<T, void> || IsChar<T>;
39
40template<typename T>
41concept IsDecayOrPointer = std::is_pointer_v<T> || std::is_pointer_v<DecayArray<T>>;
42
43template<typename From, typename To>
44concept ValidQualifiers = requires {
45 // Does not discard const
46 requires !std::is_const_v<From> || std::is_const_v<To>;
47 // Don't deal with volatile
48 requires !std::is_volatile_v<From> && !std::is_volatile_v<To>;
49};
50
51template<typename From, typename To>
52concept BaseCase = requires {
53 // Cannot cast away const
55 // At base case, neither should be pointers
56 requires !std::is_pointer_v<From> && !std::is_pointer_v<To>;
57 // Finally are the types compatible?
60};
61
62static_assert(BaseCase<char, char>);
64static_assert(BaseCase<char8_t, char>);
65static_assert(!BaseCase<const char8_t, char>);
68// Not legal to cast to char8_t
69static_assert(!BaseCase<void, char8_t>);
70// No pointers
71static_assert(!BaseCase<void *, char8_t>);
72static_assert(!BaseCase<char *, char *>);
73
74// Required to be written in the old style because recursion in concepts is not
75// allowed. Personally I think the committee hates fun.
76template<typename From, typename To, typename = void>
77struct RecursionHelper : std::false_type
78{};
79
80template<typename From, typename To>
81struct RecursionHelper<From, To, std::enable_if_t<BaseCase<From, To>>> : std::true_type
82{};
83
84template<typename From, typename To>
86 From,
87 To,
88 std::enable_if_t<std::is_pointer_v<From> && std::is_pointer_v<To> && ValidQualifiers<From, To>>>
89 : RecursionHelper<std::remove_pointer_t<From>, std::remove_pointer_t<To>>
90{};
91
92template<typename From, typename To>
93concept IsCharCastable = requires {
94 // We only decay arrays in From for safety reasons. There is almost no reason
95 // to cast *into* an array and such code probably needs closer inspection
96 // anyway.
97 requires RecursionHelper<DecayArray<From>, To>::value;
98 requires IsDecayOrPointer<From> && std::is_pointer_v<To>;
99};
100
101static_assert(!IsCharCastable<char **, char *>);
102static_assert(IsCharCastable<char *, char *>);
110static_assert(!IsCharCastable<char, char>);
114}
115
133template<typename To, typename From>
135inline To charptr_cast(From p)
136{
137 // NOLINTNEXTLINE(lix-charptrcast): stop the linter ever getting too clever and causing funny recursion
138 return reinterpret_cast<To>(p);
139}
140
141}
Definition charptr-cast.hh:52
Definition charptr-cast.hh:93
Definition charptr-cast.hh:35
Definition charptr-cast.hh:41
Definition charptr-cast.hh:44
Definition charptr-cast.hh:78