Commit b4388123 authored by Victor Zverovich's avatar Victor Zverovich

Clean up is_output_iterator

parent bc15e370
...@@ -208,6 +208,9 @@ struct monostate {}; ...@@ -208,6 +208,9 @@ struct monostate {};
namespace internal { namespace internal {
// A workaround for gcc 4.8 to make void_t work in a SFINAE context.
template <typename... Ts> struct void_t_impl { using type = void; };
#if defined(FMT_USE_STRING_VIEW) #if defined(FMT_USE_STRING_VIEW)
template <typename Char> using std_string_view = std::basic_string_view<Char>; template <typename Char> using std_string_view = std::basic_string_view<Char>;
#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW) #elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
...@@ -225,6 +228,9 @@ FMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value) { ...@@ -225,6 +228,9 @@ FMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value) {
} }
} // namespace internal } // namespace internal
template <typename... Ts>
using void_t = typename internal::void_t_impl<Ts...>::type;
/** /**
An implementation of ``std::basic_string_view`` for pre-C++17. It provides a An implementation of ``std::basic_string_view`` for pre-C++17. It provides a
subset of the API. ``fmt::basic_string_view`` is used for format strings even subset of the API. ``fmt::basic_string_view`` is used for format strings even
......
...@@ -216,6 +216,39 @@ inline Dest bit_cast(const Source& source) { ...@@ -216,6 +216,39 @@ inline Dest bit_cast(const Source& source) {
template <typename T> template <typename T>
using iterator_t = decltype(std::begin(std::declval<T&>())); using iterator_t = decltype(std::begin(std::declval<T&>()));
// Detect the iterator category of *any* given type in a SFINAE-friendly way.
// Unfortunately, older implementations of std::iterator_traits are not safe
// for use in a SFINAE-context.
template <typename It, typename Enable = void>
struct iterator_category : std::false_type {};
template <typename T> struct iterator_category<T*> {
using type = std::random_access_iterator_tag;
};
template <typename It>
struct iterator_category<It, void_t<typename It::iterator_category>> {
using type = typename It::iterator_category;
};
// Detect if *any* given type models the OutputIterator concept.
template <typename It> class is_output_iterator {
// Check for mutability because all iterator categories derived from
// std::input_iterator_tag *may* also meet the requirements of an
// OutputIterator, thereby falling into the category of 'mutable iterators'
// [iterator.requirements.general] clause 4. The compiler reveals this
// property only at the point of *actually dereferencing* the iterator!
template <typename U>
static decltype(*(std::declval<U>())) test(std::input_iterator_tag);
template <typename U> static char& test(std::output_iterator_tag);
template <typename U> static const char& test(...);
using type = decltype(test<It>(typename iterator_category<It>::type{}));
public:
static const bool value = !std::is_const<remove_reference_t<type>>::value;
};
// A workaround for std::string not having mutable data() until C++17. // A workaround for std::string not having mutable data() until C++17.
template <typename Char> inline Char* get_data(std::basic_string<Char>& s) { template <typename Char> inline Char* get_data(std::basic_string<Char>& s) {
return &s[0]; return &s[0];
...@@ -3306,48 +3339,6 @@ inline typename buffer_context<Char>::iterator format_to( ...@@ -3306,48 +3339,6 @@ inline typename buffer_context<Char>::iterator format_to(
basic_format_args<context>(as)); basic_format_args<context>(as));
} }
namespace internal {
// Detect the iterator category of *any* given type in a SFINAE-friendly way.
// Unfortunately, older implementations of std::iterator_traits are not safe
// for use in a SFINAE-context.
// the gist of C++17's void_t magic
template <typename... Ts> struct void_ { typedef void type; };
template <typename T, typename Enable = void>
struct it_category : std::false_type {};
template <typename T> struct it_category<T*> {
typedef std::random_access_iterator_tag type;
};
template <typename T>
struct it_category<T, typename void_<typename T::iterator_category>::type> {
typedef typename T::iterator_category type;
};
// Detect if *any* given type models the OutputIterator concept.
template <typename It> class is_output_iterator {
// Check for mutability because all iterator categories derived from
// std::input_iterator_tag *may* also meet the requirements of an
// OutputIterator, thereby falling into the category of 'mutable iterators'
// [iterator.requirements.general] clause 4.
// The compiler reveals this property only at the point of *actually
// dereferencing* the iterator!
template <typename U>
static decltype(*(std::declval<U>())) test(std::input_iterator_tag);
template <typename U> static char& test(std::output_iterator_tag);
template <typename U> static const char& test(...);
typedef decltype(test<It>(typename it_category<It>::type{})) type;
typedef remove_reference_t<type> result;
public:
static const bool value = !std::is_const<result>::value;
};
} // namespace internal
template <typename OutputIt, typename Char = char> template <typename OutputIt, typename Char = char>
// using format_context_t = basic_format_context<OutputIt, Char>; // using format_context_t = basic_format_context<OutputIt, Char>;
struct format_context_t { struct format_context_t {
......
...@@ -514,9 +514,8 @@ struct parts_container_concept_check : std::true_type { ...@@ -514,9 +514,8 @@ struct parts_container_concept_check : std::true_type {
template <typename T, typename = void> template <typename T, typename = void>
struct has_format_part_type : std::false_type {}; struct has_format_part_type : std::false_type {};
template <typename T> template <typename T>
struct has_format_part_type< struct has_format_part_type<T, void_t<typename T::format_part_type>>
T, typename void_<typename T::format_part_type>::type> : std::true_type { : std::true_type {};
};
static_assert(has_format_part_type<PartsContainer>::value, static_assert(has_format_part_type<PartsContainer>::value,
"PartsContainer doesn't provide format_part_type typedef"); "PartsContainer doesn't provide format_part_type typedef");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment