#ifndef CORE_INTERNAL_HPP #define CORE_INTERNAL_HPP /* This is a header containing common implementation specific code, to * reduce the complexity of the other headers, especially those that are * closely intertwined, such as and * * Additionally, some of this code is duplicated elsewhere (such as class_of, * and meta::identity), but aliases are placed to lessen any impact that this * might have. */ #include #include #include #include #include namespace core { inline namespace v2 { namespace impl { template class, class...> struct make_detect : meta::identity { using value_t = ::std::false_type; }; template class U, class... Args> struct make_detect>, U, Args...> : meta::identity> { using value_t = ::std::true_type; }; /* extremely useful custom type traits */ template struct class_of : meta::identity { }; template struct class_of : meta::identity { }; /* aliases */ template using class_of_t = typename class_of::type; template using decay_t = typename ::std::decay::type; template using remove_reference_t = typename ::std::remove_reference::type; template using enable_if_t = typename ::std::enable_if::type; /* is_nothrow_swappable plumbing */ using ::std::declval; using ::std::swap; // MSVC 2015 workaround template struct is_swappable_with { template static auto test (void*) noexcept(true) -> decltype( swap(declval(), declval()) ); template static void test (...) noexcept(false); static constexpr bool value = noexcept(test(nullptr)); }; // MSVC 2015 workaround template struct is_noexcept_swappable_with { template < class X, class Y, bool B=noexcept(swap(declval(), declval())) > static void test (enable_if_t*) noexcept(true); template static void test (...) noexcept(false); static constexpr bool value = noexcept(test(nullptr)); }; template struct is_swappable : ::std::false_type { }; template struct is_swappable< T, U, meta::deduce< is_swappable_with, is_swappable_with > > : ::std::true_type { }; template struct is_nothrow_swappable : meta::all_t< is_swappable::value, is_noexcept_swappable_with::value, is_noexcept_swappable_with::value > { }; /* * If I can't amuse myself when working with C++ templates, then life isn't * worth living. Bury me with my chevrons. */ template constexpr T&& pass (remove_reference_t& t) noexcept { return static_cast(t); } template constexpr T&& pass (remove_reference_t&& t) noexcept { return static_cast(t); } /* INVOKE pseudo-expression plumbing, *much* more simplified than previous * versions of Core */ struct undefined { constexpr undefined (...) noexcept { } }; /* We get some weird warnings under clang, so we actually give these functions * a body to get rid of it. */ template constexpr undefined INVOKE (undefined, Args&&...) noexcept { return undefined { }; } template constexpr auto INVOKE (Functor&& f, Args&&... args) -> enable_if_t< not ::std::is_member_pointer>::value, decltype(pass(f)(pass(args)...)) > { return pass(f)(pass(args)...); } template auto INVOKE (Functor&& f, Args&&... args) -> enable_if_t< ::std::is_member_pointer>::value, decltype(::std::mem_fn(pass(f))(pass(args)...)) > { return ::std::mem_fn(pass(f))(pass(args)...); } template struct invoke_of { }; template struct invoke_of : meta::identity()...))> { }; }}} /* namespace core::v2::impl */ #endif /* CORE_INTERNAL_HPP */