#pragma once #include #include "function_traits.h" #ifdef _MSC_VER #include #endif namespace vlc { #if (defined(_MSC_VER) && _MSC_VER <= 1800) || (!defined(_MSC_VER) && __cplusplus <= 201103L) template std::unique_ptr make_unique(Args&& ...args) { return std::unique_ptr(new T(std::forward(args)...)); } #else using std::make_unique; #endif template struct index_sequence { using type = index_sequence; using value_type = size_t; static constexpr std::size_t size() noexcept { return sizeof...(Ints); } }; // -------------------------------------------------------------- template struct _merge_and_renumber; template struct _merge_and_renumber, index_sequence> : index_sequence { }; // -------------------------------------------------------------- template struct make_index_sequence : _merge_and_renumber::type, typename make_index_sequence::type> { }; template<> struct make_index_sequence<0> : index_sequence<> { }; template<> struct make_index_sequence<1> : index_sequence<0> { }; namespace detail { template struct target_type { typedef void type; }; template struct target_type { typedef Class type; }; //Is reference to pointer target or derived template struct is_target_reference : public std::integral_constant< bool, std::is_reference::value && std::is_base_of< typename target_type::type, typename std::decay::type >::value > {}; } // Minimal invoke implementation from https://github.com/tomaszkam/proposals/blob/master/implementation/invoke/invoke_cpp11.hpp template constexpr auto invoke(Functor&& functor, Object&& object, Args&&... args) -> typename std::enable_if< std::is_member_function_pointer< typename std::decay::type >::value && detail::is_target_reference< Object&&, typename std::decay::type >::value, decltype((std::forward(object).*functor)(std::forward(args)...)) >::type { return (std::forward(object).*functor)(std::forward(args)...); } template constexpr auto invoke(Functor&& functor, Object&& object, Args&&... args) -> typename std::enable_if< std::is_member_function_pointer< typename std::decay::type >::value && !detail::is_target_reference< Object&&, typename std::decay::type >::value, decltype(((*std::forward(object)).*functor)(std::forward(args)...)) >::type { return ((*std::forward(object)).*functor)(std::forward(args)...); } template constexpr auto invoke(Functor&& functor, Object&& object) -> typename std::enable_if< std::is_member_object_pointer< typename std::decay::type >::value && detail::is_target_reference< Object&&, typename std::decay::type >::value, decltype((std::forward(object).*functor)) >::type { return std::forward(object).*functor; } template constexpr auto invoke(Functor&& functor, Object&& object) -> typename std::enable_if < std::is_member_object_pointer< typename std::decay::type >::value && !detail::is_target_reference< Object&&, typename std::decay::type >::value, decltype((*std::forward(object)).*functor) > ::type { return (*std::forward(object)).*functor; } template constexpr auto invoke(Functor&& functor, Args&&... args) -> typename std::enable_if< !std::is_member_pointer< typename std::decay::type >::value, decltype(std::forward(functor)(std::forward(args)...)) >::type { return std::forward(functor)(std::forward(args)...); } namespace detail { template constexpr auto apply_impl(Fn&& f, ArgsTuple&& tpl, index_sequence) -> decltype(vlc::invoke(std::forward(f), std::get(std::forward(tpl))...)) { return vlc::invoke(std::forward(f), std::get(std::forward(tpl))...); } } template constexpr auto apply(Fn&& f, ArgsTuple&& tpl) -> decltype( detail::apply_impl(std::forward(f), std::forward(tpl), make_index_sequence::type>::value> {}) ) { return detail::apply_impl(std::forward(f), std::forward(tpl), make_index_sequence::type>::value> {}); } template constexpr auto data(C& c) -> decltype(c.data()) { return c.data(); } template constexpr auto data(const C& c) -> decltype(c.data()) { return c.data(); } template constexpr T* data(T (&array)[N]) noexcept { return array; } template constexpr const E* data(std::initializer_list il) noexcept { return il.begin(); } constexpr void data(...); template constexpr auto size(const C& c) -> decltype(c.size()) { return c.size(); } template constexpr std::size_t size(const T(&array)[N]) noexcept { return N; } template constexpr std::ptrdiff_t ssize(const T(&array)[N]) noexcept { return N; } inline size_t align_up(size_t size, size_t alignment) { assert((alignment & ~(alignment - 1)) == alignment); // Alignment should be power of two return (size + alignment - 1) & ~(alignment - 1); } inline void* align_ptr(void* ptr, size_t alignment) { assert((alignment & ~(alignment - 1)) == alignment); // Alignment should be power of two return reinterpret_cast(align_up(reinterpret_cast(ptr), alignment)); } inline bool is_aligned(const void* ptr, size_t alignment) { assert((alignment & ~(alignment - 1)) == alignment); // Alignment should be power of two return (uintptr_t(ptr) & (alignment - 1)) == 0; } inline uint32_t ctz(uint64_t x) { #ifdef _MSC_VER unsigned long trailing_zero = 0; #ifdef _WIN64 if (!_BitScanForward64(&trailing_zero, x)) { return 64; } #else if (!_BitScanForward(&trailing_zero, (uint32_t)x)) { if (!_BitScanForward(&trailing_zero, (uint32_t)(x >> 32))) { return 64; } trailing_zero += 32; } #endif return trailing_zero; #else return x != 0ull ? (uint32_t)__builtin_ctzll(x) : 64; #endif } inline uint32_t clz(uint64_t x) { #ifdef _MSC_VER unsigned long leading_zero = 0; #ifdef _WIN64 if (!_BitScanReverse64(&leading_zero, x)) { return 64; } return 63 - leading_zero; #else if (!_BitScanReverse(&leading_zero, (uint32_t)(x >> 32))) { if (!_BitScanReverse(&leading_zero, (uint32_t)x)) { return 64; } return 32 + 31 - leading_zero; } return 31 - leading_zero; #endif #else return x != 0ull ? (uint32_t)__builtin_clzll(x) : 64; #endif } }