You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

107 lines
3.6 KiB

#pragma once
#include <memory>
#include <concepts>
#include <utility>
#include "macros.hh"
namespace where {
#if 0
//XXX: I think this is fine? auto&& rvalue references seem to bind to const& references anyway?
constexpr auto const& as_const( auto& t ) noexcept { return std::as_const(FORWARD(t)); }
constexpr auto const&& as_const( auto&& t ) noexcept {
using T = decltype(t);
static_assert(!std::is_reference_t<T>, "Bad decltype(auto&&)");
return static_cast<std::add_const_t<T>&&>(t);
}
#endif
template<typename T>
using add_const_reference_t = decltype((std::as_const(std::declval<T>())));
template<typename T>
using add_const_pointer_t = decltype(std::addressof(std::as_const(std::declval<T>())));
template<typename T>
concept is_polymorphic = requires(requires(T* ptr) { dynamic_cast<void const*>(ptr); });
static_assert(
std::is_lvalue_reference_v<add_const_reference_t<int>>
and std::is_lvalue_reference_v<add_const_reference_t<int const&>>
and std::is_lvalue_reference_v<add_const_reference_t<int &&>
and std::is_lvalue_reference_v<add_const_reference_t<int const&&>
and std::is_same_v
< add_const_reference_t<std::unique_ptr<int>&>
, std::unique_ptr<int> const&
>
, "add_const_reference_t is not perfectly forwarding");
template<typename P>
concept pointer_like = requires {
typename std::pointer_traits<P>;
typename std::pointer_traits<P>::element_type;
typename std::pointer_traits<P>::pointer;
};
template<typename P, typename T, bool Noexcept = true>
concept deref_to = pointer_like<P>
and requires(P ptr) {
// element type can be assigned to `T`.
requires(std::is_convertible_v<std::pointer_traits<P>::element_type, T>);
// Dereferencing the pointer can be assigned to `T`.
{ *ptr } noexcept(Noexcept) -> std::convertible_to<std::pointer_traits<P>::element_type>;
//{ ptr <=> nullptr } noexcept(Noexcept) -> std::convertible_to<
// { std::as_const(*ptr) } noexcept(Noexcept) -> std::convertible_to<add_const_reference_t<T>>;
// { std::addressof(value) } -> std::convertible_to<std::pointer_traits<P>::pointer>;
};
template<typename P, typename T, bool Noexcept = true>
concept may_deref_to = deref_to<P, T, Noexcept>
and requires(P ptr) {
// The pointer is nullable
{ ptr } noexcept(Noexcept) -> std::convertible_to<bool>;
{ !ptr } noexcept(Noexcept) -> std::convertible_to<bool>;
// The pointer can be constructed from `nullptr`.
//{ nullptr } noexcept(Noexcept) -> std::convertible_to<P>;
// The pointer can be assigned `nullptr`.
//{ ptr = nullptr } noexcept(Noexcept);
// The pointer is orderable.
//{ ptr == ptr } noexcept(Noexcept) -> std::convertible_to<bool>;
//{ ptr != ptr } noexcept(Noexcept) -> std::convertible_to<bool>;
// The pointer is null-comparable
{ ptr == nullptr } noexcept(Noexcept) -> std::convertible_to<bool>;
{ ptr != nullptr } noexcept(Noexcept) -> std::convertible_to<bool>;
};
// { std::as_const(*ptr) } noexcept -> std::convertible_to<add_const_reference_t<T>>;
// { std::addressof(value) } noexcept -> std::convertible_to<P>;
/*requires(std::is_convertible_v
< add_const_reference_t< std::pointer_traits<P>::element_type >
, add_const_reference_t< T >
>);
{ std::as_const(*std::declval<std::pointer_traits<P>::pointer>()) }
-> std::convertible_to<std::pointer_traits<P>::element_type>;
//std::convertible_to< add_const_pointer_t<*/
//};
#if 0
(std::is_pointer_v<P> &&
// P = ?*
requires(P ptr) {
{ ptr } -> std::convertible_to<T const*>;
{ static_cast<T*>(ptr) };
}
)
or requires(P ptr, T value) {
};
#endif
}