56 lines
1.6 KiB
C++
56 lines
1.6 KiB
C++
|
|
#pragma once
|
|
|
|
#ifndef MIJIN_UTIL_FUNCTIONAL_HPP_INCLUDED
|
|
#define MIJIN_UTIL_FUNCTIONAL_HPP_INCLUDED 1
|
|
|
|
#include "./concepts.hpp"
|
|
|
|
namespace mijin
|
|
{
|
|
|
|
//
|
|
// public types
|
|
//
|
|
|
|
template<auto field>
|
|
struct field_getter
|
|
{
|
|
[[nodiscard]]
|
|
constexpr decltype(auto) operator()(auto& object) const noexcept
|
|
{
|
|
return (object.*field);
|
|
}
|
|
};
|
|
|
|
template<typename T, typename TFrom>
|
|
concept basic_projection = requires(std::add_const_t<T> value, std::add_rvalue_reference_t<std::add_const_t<TFrom>> from)
|
|
{
|
|
{ std::invoke(value, from) } -> not_same_as<void>;
|
|
};
|
|
|
|
template<typename T, typename TFrom, template<typename> typename TConstraint>
|
|
concept constrained_projection =
|
|
basic_projection<T, TFrom>
|
|
&& TConstraint<decltype(std::invoke(std::declval<const T>(), std::declval<const TFrom&>()))>::value;
|
|
|
|
template<typename T, typename TFrom, typename TTo>
|
|
concept projection =
|
|
basic_projection<T, TFrom>
|
|
&& requires(std::add_const_t<T> value, std::add_rvalue_reference_t<std::add_const_t<TFrom>> from)
|
|
{
|
|
{ std::invoke(value, from) } -> implicitly_convertible<TTo>;
|
|
};
|
|
|
|
template<typename T, basic_projection<T> TProjection>
|
|
using projected_t = std::invoke_result_t<TProjection, std::add_rvalue_reference_t<std::add_const_t<T>>>;
|
|
|
|
template<typename T, typename TElement>
|
|
concept ordering = requires(std::add_const_t<T> value, std::add_rvalue_reference_t<std::add_const_t<TElement>> left, std::add_rvalue_reference_t<std::add_const_t<TElement>> right)
|
|
{
|
|
{ std::invoke(value, left, right) } -> implicitly_convertible<bool>;
|
|
};
|
|
} // namespace mijin
|
|
|
|
#endif // MIJIN_UTIL_FUNCTIONAL_HPP_INCLUDED
|