mirror of
https://github.com/fmtlib/fmt.git
synced 2025-01-27 15:35:18 +00:00
Clean up is_output_iterator
This commit is contained in:
parent
bc15e3700e
commit
b438812324
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user