Clean up is_output_iterator

This commit is contained in:
Victor Zverovich 2019-07-07 11:45:25 -07:00
parent bc15e3700e
commit b438812324
3 changed files with 41 additions and 45 deletions

View File

@ -208,6 +208,9 @@ struct monostate {};
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)
template <typename Char> using std_string_view = std::basic_string_view<Char>;
#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
@ -225,6 +228,9 @@ FMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value) {
}
} // 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
subset of the API. ``fmt::basic_string_view`` is used for format strings even

View File

@ -216,6 +216,39 @@ inline Dest bit_cast(const Source& source) {
template <typename 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.
template <typename Char> inline Char* get_data(std::basic_string<Char>& s) {
return &s[0];
@ -3306,48 +3339,6 @@ inline typename buffer_context<Char>::iterator format_to(
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>
// using format_context_t = basic_format_context<OutputIt, Char>;
struct format_context_t {

View File

@ -514,9 +514,8 @@ struct parts_container_concept_check : std::true_type {
template <typename T, typename = void>
struct has_format_part_type : std::false_type {};
template <typename T>
struct has_format_part_type<
T, typename void_<typename T::format_part_type>::type> : std::true_type {
};
struct has_format_part_type<T, void_t<typename T::format_part_type>>
: std::true_type {};
static_assert(has_format_part_type<PartsContainer>::value,
"PartsContainer doesn't provide format_part_type typedef");