Files
mijin2/source/mijin/util/functional.hpp

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