diff --git a/include/fmt/base.h b/include/fmt/base.h index 9e55ba1ec9ae..78a2093e4547 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -593,7 +593,20 @@ template class basic_appender; using appender = basic_appender; // Checks whether T is a container with contiguous storage. -template struct is_contiguous : std::false_type {}; +namespace detail { + +template +struct is_contiguous_ : std::false_type {}; + +template +struct is_contiguous_().data()), + decltype(std::declval().size()), + decltype(std::declval()[size_t{}])>> + : std::true_type {}; + +} // namespace detail + +template struct is_contiguous : detail::is_contiguous_ {}; class context; template class generic_context; diff --git a/test/base-test.cc b/test/base-test.cc index 9575e05555fe..dc62eea83296 100644 --- a/test/base-test.cc +++ b/test/base-test.cc @@ -21,8 +21,10 @@ #include // std::equal_to #include // std::back_insert_iterator, std::distance #include // std::numeric_limits +#include // std::list #include // std::string #include // std::is_same +#include // std::vector #include "gmock/gmock.h" @@ -876,6 +878,14 @@ FMT_BEGIN_NAMESPACE template <> struct is_contiguous : std::true_type {}; FMT_END_NAMESPACE +TEST(base_test, is_contiguous) { + EXPECT_TRUE((fmt::is_contiguous::value)); + EXPECT_TRUE((fmt::is_contiguous::value)); + EXPECT_TRUE((fmt::is_contiguous::value)); + EXPECT_TRUE((fmt::is_contiguous>::value)); + EXPECT_FALSE((fmt::is_contiguous>::value)); +} + TEST(base_test, format_to_custom_container) { auto c = custom_container(); fmt::format_to(std::back_inserter(c), "");