145 using self_type = named<T, PARAMETER, TRAITS...>;
146 static constexpr detail::FixedString name = PARAMETER;
150 template <
typename... TYPES>
153 template <
template <
typename...>
typename TRAIT_TYPE,
typename... REST>
154 static constexpr auto find_trait_type_impl(TRAIT_TYPE<REST...>)
156 return std::type_identity<std::remove_cvref_t<TRAIT_TYPE<REST...>>>{};
158 template <
template <
typename...>
typename TRAIT_TYPE,
typename... REST>
159 static constexpr auto find_trait_type_impl(...)
161 return std::type_identity<void>{};
164 template <
template <
typename...>
typename TRAIT_TYPE,
typename GIVEN_PACK,
typename... REST>
165 static constexpr auto find_trait_type_impl(GIVEN_PACK, TRAIT_TYPE<REST...>)
167 return []<
typename U,
typename... GIVEN_TYPES>(type_pack<GIVEN_TYPES...>, U) {
168 return [] <
typename... SOME>(TRAIT_TYPE<GIVEN_TYPES..., SOME...>) {
169 return find_trait_type_impl(TRAIT_TYPE<GIVEN_TYPES..., SOME...>{});
171 }(GIVEN_PACK{}, TRAIT_TYPE<REST...>{});
174 template <
template <
typename...>
typename TRAIT_TYPE,
typename GIVEN_PACK,
typename FIRST_TRAIT,
typename... REST>
175 static constexpr auto find_trait_type_traits(FIRST_TRAIT trait, REST... traits)
177 using type_candidate = std::remove_cvref_t<typename decltype(find_trait_type_impl<TRAIT_TYPE>(GIVEN_PACK{}, trait))::type > ;
178 if constexpr (std::is_same_v<type_candidate, void>)
179 return find_trait_type_traits<TRAIT_TYPE, GIVEN_PACK>(traits...);
181 return std::type_identity<type_candidate>{};
184 template <
template <
typename...>
typename TRAIT_TYPE,
typename... GIVEN>
185 static constexpr auto find_trait_type_traits() {
return std::type_identity<void>{}; }
187 template <
template <
typename...>
typename TRAIT_TYPE,
typename... GIVEN>
188 static constexpr auto find_trait_type()
190 return find_trait_type_traits<TRAIT_TYPE, type_pack<GIVEN...>>(TRAITS{}...);
193 template <
template <
typename...>
typename TRAIT_TYPE,
typename... GIVEN>
194 using concrete_trait_type_of =
typename decltype(find_trait_type<TRAIT_TYPE, GIVEN...>())::type;
196 static constexpr auto find_displacement_type()
198 using trait = concrete_trait_type_of<traits::is_location_of>;
199 if constexpr (std::is_same_v<trait, void>)
200 return std::type_identity<void>{};
202 return std::type_identity<typename trait::displacement_type>{};
207 template <
typename TRAIT,
typename... OTHER>
208 static constexpr bool has_trait = (std::is_same_v<TRAIT, TRAITS> || ...) && TRAIT::template applies_to<self_type, OTHER...>;
215 template <
typename... ARGS>
216 requires std::constructible_from<T, ARGS...>
217 constexpr explicit named(ARGS&&... args)
noexcept(std::is_nothrow_constructible_v<T, ARGS...>) : value(std::forward<ARGS>(args)...) {}
219 template <
typename U>
220 requires has_trait<traits::implicitly_constructible> && std::is_same_v<std::remove_cvref_t<U>, T>
221 constexpr named(U&& arg)
noexcept(std::is_nothrow_move_constructible_v<T>)
222 : value(std::forward<U>(arg))
226 template <
typename U>
227 requires has_trait<traits::implicitly_constructible_from<U>>
228 constexpr named(U&& arg)
noexcept(std::is_nothrow_move_constructible_v<T>)
229 : value((T)std::forward<U>(arg))
233 template <
typename U>
234 requires (!std::is_same_v<concrete_trait_type_of<traits::constructible_using, std::remove_cvref_t<U>>,
void>)
235 constexpr named(U&& arg)
noexcept(std::is_nothrow_move_constructible_v<T>)
236 : value(typename concrete_trait_type_of<traits::constructible_using, std::remove_cvref_t<U>>::convertor{}(arg))
240 constexpr named() noexcept(std::is_nothrow_default_constructible_v<T>) = default;
241 constexpr named(named const&) noexcept(std::is_nothrow_copy_constructible_v<T>) = default;
242 constexpr named(named&&) noexcept(std::is_nothrow_move_constructible_v<T>) = default;
243 constexpr named& operator=(named const&) noexcept(std::is_nothrow_copy_assignable_v<T>) = default;
244 constexpr named& operator=(named&&) noexcept(std::is_nothrow_move_assignable_v<T>) = default;
246 template <typename U>
247 requires requires(U&& val) { { named_cast<self_type>(std::forward<U>(val)) } -> std::same_as<self_type>; }
248 constexpr named(U&& arg)
249 : named(named_cast<self_type>(std::forward<U>(arg)))
254 constexpr T& operator*() &
noexcept {
return value; }
255 constexpr T
const& operator*() const & noexcept {
return value; }
256 constexpr T operator*() &&
noexcept {
return std::move(value); }
258 constexpr T* operator->() noexcept {
return &value; }
259 constexpr T
const* operator->() const noexcept {
return &value; }
261 constexpr T& get() &
noexcept {
return value; }
262 constexpr T
const& get() const& noexcept {
return value; }
263 constexpr T get() &&
noexcept {
return std::move(value); }
265 template <
typename U>
266 constexpr U as() noexcept {
return static_cast<U
>(value); }
268 constexpr auto drop() noexcept(std::is_nothrow_move_constructible_v<T>) {
return std::move(value); }
270 template <
typename U, detail::FixedString OTHER_PARAMETER,
typename... OTHER_CAPABILITIES>
271 requires requires(self_type
const& self) { { named_cast<named<U, OTHER_PARAMETER, OTHER_CAPABILITIES...>>(self) } -> std::same_as<named<U, OTHER_PARAMETER, OTHER_CAPABILITIES...>>; }
272 constexpr operator named<U, OTHER_PARAMETER, OTHER_CAPABILITIES...>()
const
274 return named_cast<named<U, OTHER_PARAMETER, OTHER_CAPABILITIES...>>(*this);
277 template <
typename U>
278 requires requires(self_type
const& self) { { named_cast<U>(self) } -> std::same_as<U>; }
279 constexpr explicit operator U()
const
281 return named_cast<U>(*
this);
284 constexpr explicit operator bool() const noexcept {
return value; }
285 constexpr operator base_type() const noexcept requires has_trait<traits::implicitly_convertible> {
return value; }
287 constexpr auto operator<=>(named
const&)
const =
default;
289 template <
typename U>
290 constexpr auto operator<=>(U
const& b)
const {
return value <=> b; }
291 template <
typename U>
292 constexpr bool operator==(U
const& b)
const {
return value == b; }
295 constexpr named& operator++()
296 requires has_trait<traits::incrementable>
302 constexpr auto operator+(self_type
const& val)
const
303 requires has_trait<displacement> || has_trait<addable>
305 return self_type{ this->value + val.value };
308 constexpr auto operator-() const
309 requires has_trait<displacement>
311 return self_type{ -this->value };
314 constexpr auto operator+() const
315 requires has_trait<displacement>
317 return self_type{ +this->value };
320 constexpr auto& operator+=(self_type
const& val)
321 requires has_trait<displacement> || has_trait<addable>
323 this->value += val.value;
328 friend constexpr auto operator-(self_type
const& other, self_type
const& self)
329 requires (has_trait<displacement> || has_trait<subtractable>) && (!has_trait<location>)
331 return self_type{ other.value - self.value };
334 constexpr auto operator-(self_type
const& val)
const
335 requires (has_trait<location>) && (!std::same_as<displacement_type, void>)
341 template <
typename LOCATION_TYPE>
344 (has_trait<displacement>) &&
345 (traits::applies_to<LOCATION_TYPE, location>) &&
346 (traits::named_is_displacement_of<self_type, LOCATION_TYPE>) &&
347 (addable::applies_to<self_type, LOCATION_TYPE>)
349 return std::remove_cvref_t<LOCATION_TYPE>{ this->value + std::forward<LOCATION_TYPE>(val).value };
353 template <
typename DISPLACEMENT_TYPE>
356 (has_trait<location>) &&
357 (traits::applies_to<DISPLACEMENT_TYPE, displacement>) &&
358 (traits::named_is_displacement_of<DISPLACEMENT_TYPE, self_type>) &&
359 (addable::applies_to<self_type, DISPLACEMENT_TYPE>)
361 return self_type{ this->value + std::forward<DISPLACEMENT_TYPE>(val).value };
364 template <
typename U>
365 constexpr auto operator*(U&& val)
const
366 requires has_trait<displacement> && std::constructible_from<T, decltype(std::declval<T>() * std::declval<U>())>
368 return self_type{ this->value * std::forward<U>(val) };
371 template <
typename U>
372 friend constexpr auto operator*(U&& val, named self)
373 requires has_trait<displacement> && std::constructible_from<T, decltype(std::declval<T>() * std::declval<U>())>
375 return self_type{ std::forward<U>(val) * self.value};
378 template <
typename U>
379 constexpr auto operator/(U&& val)
const
380 requires has_trait<displacement> && std::constructible_from<T, decltype(std::declval<T>() / std::declval<U>())>
382 return self_type{ this->value / std::forward<U>(val) };
385 constexpr auto operator/(self_type
const& val)
const
386 requires has_trait<displacement>
388 return this->value / val.value;