/** * @file libimp/generic.h * @author mutouyun (orz@orzz.org) * @brief Tools for generic programming. * @date 2022-03-01 */ #pragma once #include #include #include "libimp/def.h" LIBIMP_NAMESPACE_BEG_ /** * @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 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 is_not_match = typename std::enable_if::type...>::value>::type; LIBIMP_NAMESPACE_END_