/** * \file libipc/generic.h * \author mutouyun (orz@orzz.org) * \brief Tools for generic programming. */ #pragma once #include #include // std::declval, std::true_type, std::false_type #include // std::size_t #include "libipc/imp/detect_plat.h" namespace ipc { /** * \brief Utility metafunction that maps a sequence of any types to the type void * \see https://en.cppreference.com/w/cpp/types/void_t */ template using void_t = void; /** * \brief A type-list for generic programming. */ template struct types {}; /** * \brief To indicate that the contained object should be constructed in-place. * \see https://en.cppreference.com/w/cpp/utility/in_place */ #if defined(LIBIPC_CPP_17) using std::in_place_t; using std::in_place; #else /*!LIBIPC_CPP_17*/ struct in_place_t { explicit in_place_t() = default; }; constexpr in_place_t in_place {}; #endif/*!LIBIPC_CPP_17*/ /** * \brief A general pattern for supporting customisable functions * \see https://www.open-std.org/jtc1/sc22/WG21/docs/papers/2019/p1895r0.pdf */ namespace detail { void tag_invoke(); struct tag_invoke_t { template constexpr auto operator()(T tag, A &&...args) const noexcept(noexcept(tag_invoke(std::forward(tag), std::forward(args)...))) -> decltype(tag_invoke(std::forward(tag), std::forward(args)...)) { return tag_invoke(std::forward(tag), std::forward(args)...); } }; } // namespace detail constexpr detail::tag_invoke_t tag_invoke {}; /** * \brief Circumventing forwarding reference may override copy and move constructs. * \see https://mpark.github.io/programming/2014/06/07/beware-of-perfect-forwarding-constructors/ */ namespace detail { template struct is_same_first : std::false_type {}; template struct is_same_first : std::true_type {}; } // namespace detail template using not_match = typename std::enable_if::type...>::value, bool>::type; /** * \brief Determines whether a type is specialized from a particular template. */ template