Это набор вспомогательных инструментов (типажей) для построения типов указателей на члены класса на основе cv/ref-квалификаторов типа объекта и дескриптора целевого члена. Эти шаблоны помогают формировать типы указателей на методы и свойства класса единообразным и выразительным способом.
#include <scl/utility/type_traits/member_like.h>Содержание:
member_function_like_t<Type, Signature>Формирует тип указателя на нестатическую функцию-член для класса Type и сигнатуры Signature, копируя cv- и ref-квалификаторы из Type и спецификатор noexcept из Signature.
template <typename Type, typename Signature> using member_function_like_t = ...;std::remove_cvref_t<Type>.const/volatile и ref-квалификатор (& или &&) функции-члена копируются из Type.Type не имеет ref-квалификатора (т.е. не является ссылкой), результирующая функция-член не будет ref-квалифицирована (без &/&&).Signature имеет вид R(Args...) noexcept, результирующий указатель на функцию-член будет noexcept; в противном случае — нет.Signature.#include <type_traits>
#include <scl/utility/type_traits/member_like.h>
struct X {};
using ::scl::member_function_like_t;
// Без ref-квалификатора и noexcept
static_assert(std::is_same_v<member_function_like_t<X, void()>, void (X::*)()>);
static_assert(std::is_same_v<member_function_like_t<X const, void()>, void (X::*)() const>);
static_assert(std::is_same_v<member_function_like_t<X volatile, void()>, void (X::*)() volatile>);
static_assert(std::is_same_v<member_function_like_t<X const volatile, void()>, void (X::*)() const volatile>);
// С lvalue-квалификатором (&), без noexcept
static_assert(std::is_same_v<member_function_like_t<X&, void()>, void (X::*)() &>);
static_assert(std::is_same_v<member_function_like_t<X const&, void()>, void (X::*)() const &>);
static_assert(std::is_same_v<member_function_like_t<X volatile&, void()>, void (X::*)() volatile &>);
static_assert(std::is_same_v<member_function_like_t<X const volatile&, void()>, void (X::*)() const volatile &>);
// С rvalue-квалификатором (&&), без noexcept
static_assert(std::is_same_v<member_function_like_t<X&&, void()>, void (X::*)() &&>);
static_assert(std::is_same_v<member_function_like_t<X const&&, void()>, void (X::*)() const &&>);
static_assert(std::is_same_v<member_function_like_t<X volatile&&, void()>, void (X::*)() volatile &&>);
static_assert(std::is_same_v<member_function_like_t<X const volatile&&, void()>, void (X::*)() const volatile &&>);
// С noexcept
static_assert(std::is_same_v<member_function_like_t<X, void() noexcept>, void (X::*)() noexcept>);
static_assert(std::is_same_v<member_function_like_t<X const, void() noexcept>, void (X::*)() const noexcept>);
// С сохранением аргументов
static_assert(std::is_same_v<member_function_like_t<X const&, int(short)>, int (X::*)(short) const &>);
member_property_like_t — Формирует типы указателей на члены-данные.member_like_t — Обобщённый селектор для формирования указателей на функции-члены и члены-данные.member_property_like_t<Type, Member>Формирует тип указателя на член-данное для класса Type и типа члена Member, накладывая cv-квалификаторы объекта на тип члена.
template <typename Type, typename Member> using member_property_like_t = ...;std::remove_cvref_t<Type>.const/volatile из Type добавляются к Member (сохраняя любые квалификаторы, уже имеющиеся у Member).Type игнорируются (члены-данные не могут быть ref-квалифицированы).MemberLikeCv (std::remove_cvref_t<Type>::*), где MemberLikeCv — это Member с добавленными const и/или volatile, если они присутствуют в Type.#include <type_traits>
#include <scl/utility/type_traits/member_like.h>
struct X { int a = 0; int const b = 1; };
using ::scl::member_property_like_t;
// Квалификаторы объекта накладываются на Member
static_assert(std::is_same_v<member_property_like_t<X, int>, int X::*>);
static_assert(std::is_same_v<member_property_like_t<X const, int>, int const X::*>);
static_assert(std::is_same_v<member_property_like_t<X volatile, int>, int volatile X::*>);
static_assert(std::is_same_v<member_property_like_t<X const volatile, int>, int const volatile X::*>);
// Ссылки на Type не влияют на члены-данные
static_assert(std::is_same_v<member_property_like_t<X&, int>, int X::*>);
static_assert(std::is_same_v<member_property_like_t<X const&, int>, int const X::*>);
// Собственные cv-квалификаторы члена сохраняются (и объединяются с квалификаторами объекта)
static_assert(std::is_same_v<member_property_like_t<X, int const>, int const X::*>);
static_assert(std::is_same_v<member_property_like_t<X const, int volatile>, int const volatile X::*>);
const или volatile квалификаторами, что помогает в обобщённом коде, где необходимо различать доступ к члену для чтения и для записи.member_function_like_t — Формирует типы указателей на функции-члены.member_like_t — Обобщённый селектор для формирования указателей на функции-члены и члены-данные.member_like_t<Type, T>Обобщённый селектор, который создаёт тип указателя на член для класса Type и дескриптора T:
T — это функциональный тип (R(Args...) или R(Args...) noexcept), ведёт себя как member_function_like_t<Type, T>.В противном случае, ведёт себя как member_property_like_t<Type, T>.
template <typename Type, typename T> using member_like_t = ...;member_like_t<Type, R(Args...) [noexcept]> даёт
R (std::remove_cvref_t<Type>::*)(Args...) [cv из Type] [ref из Type] [noexcept из T].member_like_t<Type, Member> даёт
MemberLikeCv (std::remove_cvref_t<Type>::*), где MemberLikeCv накладывает const/volatile из Type на Member.T должен быть чистым функциональным типом (не указателем или ссылкой на функцию).R(*)(Args...) или R(&)(Args...), сначала удалите указатель/ссылку.#include <type_traits>
#include <scl/utility/type_traits/member_like.h>
struct X { int a = 0; int const b = 1; };
using ::scl::member_like_t;
// Функции-члены
static_assert(std::is_same_v<member_like_t<X, void()>, void (X::*)()>);
static_assert(std::is_same_v<member_like_t<X const&, int(short)>, int (X::*)(short) const &>);
static_assert(std::is_same_v<member_like_t<X const volatile, void(int) noexcept>, void (X::*)(int) const volatile noexcept>);
// Члены-данные
static_assert(std::is_same_v<member_like_t<X, int>, int X::*>);
static_assert(std::is_same_v<member_like_t<X const, int>, int const X::*>);
static_assert(std::is_same_v<member_like_t<X, int const>, int const X::*>);
member_function_like_t — Конструктор указателей на функции-члены.member_property_like_t — Конструктор указателей на члены-данные.member_function_like_t: Type должен быть классовым типом; Signature должен быть функциональным типом (R(Args...) или R(Args...) noexcept).member_property_like_t: Type должен быть классом или объединением (union); Member не должен быть функциональным типом.