#pragma once #include #include // for std::begin #include #include // based on https://stackoverflow.com/a/31207079 template struct is_container : std::false_type {}; namespace details { template struct is_container_helper {}; } // A very loose definition of container, nerfed to fit both C-array and ColumnArrayT::ArrayWrapper template struct is_container< T, std::conditional_t< false, ::details::is_container_helper< decltype(std::declval().size()), decltype(std::begin(std::declval())), decltype(std::end(std::declval())) >, void > > : public std::true_type {}; template inline constexpr bool is_container_v = is_container::value; // Since result_of is deprecated in C++17, and invoke_result_of is unavailable until C++20... template using my_result_of_t = #if __cplusplus >= 201703L std::invoke_result_t; #else std::result_of_t; #endif // https://stackoverflow.com/a/11251408 template < template class Template, typename T > struct is_instantiation_of : std::false_type {}; template < template class Template, typename... Args > struct is_instantiation_of< Template, Template > : std::true_type {}; template inline constexpr bool is_string_v = std::is_same_v> || std::is_same_v>; // https://stackoverflow.com/a/34111095 template struct is_one_of { static constexpr bool value = false; }; template struct is_one_of { static constexpr bool value = std::is_same::value || is_one_of::value; }; template inline constexpr bool is_one_of_v = is_one_of::value; #define HAS_METHOD(FUN) \ template \ struct has_method_##FUN : std::false_type {}; \ template \ struct has_method_##FUN>> \ : std::true_type {}; \ template \ constexpr bool has_method_##FUN##_v = has_method_##FUN::value; HAS_METHOD(Reserve); HAS_METHOD(Capacity); HAS_METHOD(GetWritableData);