Utilities for building pointer-to-member types based on an object type’s cv/ref qualifiers and a target descriptor. These traits help you form pointer-to-member-function and pointer-to-data-member types in a uniform, expressive way.
#include <scl/utility/type_traits/member_like.h>Contents:
member_function_like_t<Type, Signature>Builds a pointer-to-non-static-member-function type for class Type and function Signature, mirroring the cv- and ref-qualifiers from Type and the noexcept from Signature.
template <typename Type, typename Signature> using member_function_like_t = ...;std::remove_cvref_t<Type>.const/volatile and ref-qualifier (& or &&) are copied from Type.Type has no ref-qualifier (i.e., not a reference), the resulting member function is unqualified with respect to ref (no &/&&).Signature is of the form R(Args...) noexcept, the resulting member function pointer is noexcept; otherwise it is not.Signature.#include <type_traits>
#include <scl/utility/type_traits/member_like.h>
struct X {};
using ::scl::member_function_like_t;
// No ref-qualifier, no 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-qualified (&), no 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-qualified (&&), no 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 &&>);
// With 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>);
// With arguments retained
static_assert(std::is_same_v<member_function_like_t<X const&, int(short)>, int (X::*)(short) const &>);
member_property_like_t — Forms pointer-to-data-member types.member_like_t — Generic selector between function and data member pointer formation.member_property_like_t<Type, Member>Builds a pointer-to-data-member type for class Type and member type Member, overlaying the object’s cv-qualifiers onto the member type.
template <typename Type, typename Member> using member_property_like_t = ...;std::remove_cvref_t<Type>.const/volatile qualifiers from Type are added to Member (preserving any qualifiers already on Member).Type are ignored (data members are not ref-qualified).MemberLikeCv (std::remove_cvref_t<Type>::*), where MemberLikeCv is Member with const and/or volatile added if present on Type.#include <scl/utility/type_traits/member_like.h>
struct X { int a = 0; int const b = 1; };
using ::scl::member_property_like_t;
// Object qualifiers overlay onto 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::*>);
// References on Type do not matter for data members
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::*>);
// Member’s own cv is preserved (and overlaid with object’s 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::*>);
member_function_like_t — Forms pointer-to-member-function types.member_like_t — Generic selector between function and data member pointer formation.member_like_t<Type, T>Generic selector that produces a pointer-to-member type for class Type and a descriptor T:
T is a function type (R(Args...) or R(Args...) noexcept), behaves like member_function_like_t<Type, T>.Otherwise, behaves like member_property_like_t<Type, T>.
template <typename Type, typename T> using member_like_t = ...;member_like_t<Type, R(Args...) [noexcept]> yieldsR (std::remove_cvref_t<Type>::*)(Args...) [cv from Type] [ref from Type] [noexcept from T].member_like_t<Type, Member> yieldsMemberLikeCv (std::remove_cvref_t<Type>::*), where MemberLikeCv overlays const/volatile from Type onto Member.T must be a pure function type (not a pointer or reference to function) to select the function branch.R(*)(Args...) or R(&)(Args...), strip pointer/reference first.#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;
// Function members
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>);
// Data members
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 — Pointer-to-member-function builder.member_property_like_t — Pointer-to-data-member builder.member_function_like_t, Type must be a class type; Signature must be a function type (R(Args...) or R(Args...) noexcept).member_property_like_t, Type must be a class or union type; Member must not be a function type.