mirror of
https://github.com/fmtlib/fmt.git
synced 2025-01-15 19:51:19 +00:00
Simplify is_output_iterator
This commit is contained in:
parent
da8278e1e3
commit
e3b4c22ec9
@ -567,7 +567,7 @@ inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
|
|||||||
Formats a string with the given text_style and writes the output to ``out``.
|
Formats a string with the given text_style and writes the output to ``out``.
|
||||||
*/
|
*/
|
||||||
template <typename OutputIt, typename Char,
|
template <typename OutputIt, typename Char,
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value)>
|
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
|
||||||
OutputIt vformat_to(
|
OutputIt vformat_to(
|
||||||
OutputIt out, const text_style& ts, basic_string_view<Char> format_str,
|
OutputIt out, const text_style& ts, basic_string_view<Char> format_str,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
@ -589,7 +589,7 @@ OutputIt vformat_to(
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename OutputIt, typename S, typename... Args,
|
template <typename OutputIt, typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value&&
|
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char_t<S>>::value&&
|
||||||
detail::is_string<S>::value)>
|
detail::is_string<S>::value)>
|
||||||
inline OutputIt format_to(OutputIt out, const text_style& ts,
|
inline OutputIt format_to(OutputIt out, const text_style& ts,
|
||||||
const S& format_str, Args&&... args) {
|
const S& format_str, Args&&... args) {
|
||||||
|
@ -667,10 +667,11 @@ OutputIt format_to(OutputIt out, const S&, const Args&... args) {
|
|||||||
return format_to(out, compiled, args...);
|
return format_to(out, compiled, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
||||||
typename OutputIt, typename CompiledFormat, typename... Args,
|
FMT_ENABLE_IF(detail::is_output_iterator<
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value&& std::is_base_of<
|
OutputIt, typename CompiledFormat::char_type>::value&&
|
||||||
detail::basic_compiled_format, CompiledFormat>::value)>
|
std::is_base_of<detail::basic_compiled_format,
|
||||||
|
CompiledFormat>::value)>
|
||||||
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
||||||
const CompiledFormat& cf,
|
const CompiledFormat& cf,
|
||||||
const Args&... args) {
|
const Args&... args) {
|
||||||
|
@ -801,8 +801,8 @@ template <typename T> class iterator_buffer<T*, T> final : public buffer<T> {
|
|||||||
template <typename Container>
|
template <typename Container>
|
||||||
class iterator_buffer<std::back_insert_iterator<Container>,
|
class iterator_buffer<std::back_insert_iterator<Container>,
|
||||||
enable_if_t<is_contiguous<Container>::value,
|
enable_if_t<is_contiguous<Container>::value,
|
||||||
typename Container::value_type>> final
|
typename Container::value_type>>
|
||||||
: public buffer<typename Container::value_type> {
|
final : public buffer<typename Container::value_type> {
|
||||||
private:
|
private:
|
||||||
Container& container_;
|
Container& container_;
|
||||||
|
|
||||||
@ -1371,23 +1371,15 @@ struct iterator_category<It, void_t<typename It::iterator_category>> {
|
|||||||
using type = typename It::iterator_category;
|
using type = typename It::iterator_category;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Detect if *any* given type models the OutputIterator concept.
|
template <typename It, typename T, typename Enable = void>
|
||||||
template <typename It> class is_output_iterator {
|
struct is_output_iterator : std::false_type {};
|
||||||
// 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{}));
|
template <typename It, typename T>
|
||||||
|
struct is_output_iterator<
|
||||||
public:
|
It, T,
|
||||||
enum { value = !std::is_const<remove_reference_t<type>>::value };
|
void_t<typename iterator_category<It>::type,
|
||||||
};
|
decltype(*std::declval<It>() = std::declval<T>())>>
|
||||||
|
: std::true_type {};
|
||||||
|
|
||||||
template <typename OutputIt>
|
template <typename OutputIt>
|
||||||
struct is_back_insert_iterator : std::false_type {};
|
struct is_back_insert_iterator : std::false_type {};
|
||||||
@ -1983,7 +1975,7 @@ inline void vprint_mojibake(std::FILE*, string_view, format_args) {}
|
|||||||
// GCC 8 and earlier cannot handle std::back_insert_iterator<Container> with
|
// GCC 8 and earlier cannot handle std::back_insert_iterator<Container> with
|
||||||
// vformat_to<ArgFormatter>(...) overload, so SFINAE on iterator type instead.
|
// vformat_to<ArgFormatter>(...) overload, so SFINAE on iterator type instead.
|
||||||
template <typename OutputIt, typename S, typename Char = char_t<S>,
|
template <typename OutputIt, typename S, typename Char = char_t<S>,
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value)>
|
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
|
||||||
OutputIt vformat_to(
|
OutputIt vformat_to(
|
||||||
OutputIt out, const S& format_str,
|
OutputIt out, const S& format_str,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
@ -2004,7 +1996,8 @@ OutputIt vformat_to(
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename OutputIt, typename S, typename... Args,
|
template <typename OutputIt, typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value&&
|
typename Char = char_t<S>,
|
||||||
|
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||||
detail::is_string<S>::value)>
|
detail::is_string<S>::value)>
|
||||||
inline OutputIt format_to(OutputIt out, const S& format_str, Args&&... args) {
|
inline OutputIt format_to(OutputIt out, const S& format_str, Args&&... args) {
|
||||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||||
@ -2019,7 +2012,7 @@ template <typename OutputIt> struct format_to_n_result {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename OutputIt, typename Char, typename... Args,
|
template <typename OutputIt, typename Char, typename... Args,
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value)>
|
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
|
||||||
inline format_to_n_result<OutputIt> vformat_to_n(
|
inline format_to_n_result<OutputIt> vformat_to_n(
|
||||||
OutputIt out, size_t n, basic_string_view<Char> format_str,
|
OutputIt out, size_t n, basic_string_view<Char> format_str,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
@ -2037,8 +2030,8 @@ inline format_to_n_result<OutputIt> vformat_to_n(
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename OutputIt, typename S, typename... Args,
|
template <typename OutputIt, typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(detail::is_string<S>::value&&
|
FMT_ENABLE_IF(detail::is_string<S>::value&& detail::
|
||||||
detail::is_output_iterator<OutputIt>::value)>
|
is_output_iterator<OutputIt, char_t<S>>::value)>
|
||||||
inline format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
inline format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
||||||
const S& format_str,
|
const S& format_str,
|
||||||
const Args&... args) {
|
const Args&... args) {
|
||||||
|
@ -45,14 +45,13 @@ inline std::basic_string<Char> vformat(
|
|||||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||||
inline std::basic_string<Char> format(const std::locale& loc,
|
inline std::basic_string<Char> format(const std::locale& loc,
|
||||||
const S& format_str, Args&&... args) {
|
const S& format_str, Args&&... args) {
|
||||||
return detail::vformat(
|
return detail::vformat(loc, to_string_view(format_str),
|
||||||
loc, to_string_view(format_str),
|
|
||||||
fmt::make_args_checked<Args...>(format_str, args...));
|
fmt::make_args_checked<Args...>(format_str, args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename OutputIt, typename... Args,
|
template <typename S, typename OutputIt, typename... Args,
|
||||||
typename Char = enable_if_t<
|
typename Char = char_t<S>,
|
||||||
detail::is_output_iterator<OutputIt>::value, char_t<S>>>
|
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
|
||||||
inline OutputIt vformat_to(
|
inline OutputIt vformat_to(
|
||||||
OutputIt out, const std::locale& loc, const S& format_str,
|
OutputIt out, const std::locale& loc, const S& format_str,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
@ -65,8 +64,8 @@ inline OutputIt vformat_to(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename S, typename... Args,
|
template <typename OutputIt, typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value&&
|
typename Char = char_t<S>,
|
||||||
detail::is_string<S>::value)>
|
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
|
||||||
inline OutputIt format_to(OutputIt out, const std::locale& loc,
|
inline OutputIt format_to(OutputIt out, const std::locale& loc,
|
||||||
const S& format_str, Args&&... args) {
|
const S& format_str, Args&&... args) {
|
||||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||||
|
@ -169,20 +169,22 @@ TEST(IteratorTest, TruncatingBackInserter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(IteratorTest, IsOutputIterator) {
|
TEST(IteratorTest, IsOutputIterator) {
|
||||||
EXPECT_TRUE(fmt::detail::is_output_iterator<char*>::value);
|
EXPECT_TRUE((fmt::detail::is_output_iterator<char*, char>::value));
|
||||||
EXPECT_FALSE(fmt::detail::is_output_iterator<const char*>::value);
|
EXPECT_FALSE((fmt::detail::is_output_iterator<const char*, char>::value));
|
||||||
EXPECT_FALSE(fmt::detail::is_output_iterator<std::string>::value);
|
EXPECT_FALSE((fmt::detail::is_output_iterator<std::string, char>::value));
|
||||||
EXPECT_TRUE(fmt::detail::is_output_iterator<
|
|
||||||
std::back_insert_iterator<std::string>>::value);
|
|
||||||
EXPECT_TRUE(fmt::detail::is_output_iterator<std::string::iterator>::value);
|
|
||||||
EXPECT_FALSE(
|
|
||||||
fmt::detail::is_output_iterator<std::string::const_iterator>::value);
|
|
||||||
EXPECT_FALSE(fmt::detail::is_output_iterator<std::list<char>>::value);
|
|
||||||
EXPECT_TRUE(
|
EXPECT_TRUE(
|
||||||
fmt::detail::is_output_iterator<std::list<char>::iterator>::value);
|
(fmt::detail::is_output_iterator<std::back_insert_iterator<std::string>,
|
||||||
EXPECT_FALSE(
|
char>::value));
|
||||||
fmt::detail::is_output_iterator<std::list<char>::const_iterator>::value);
|
EXPECT_TRUE(
|
||||||
EXPECT_FALSE(fmt::detail::is_output_iterator<uint32_pair>::value);
|
(fmt::detail::is_output_iterator<std::string::iterator, char>::value));
|
||||||
|
EXPECT_FALSE((fmt::detail::is_output_iterator<std::string::const_iterator,
|
||||||
|
char>::value));
|
||||||
|
EXPECT_FALSE((fmt::detail::is_output_iterator<std::list<char>, char>::value));
|
||||||
|
EXPECT_TRUE((
|
||||||
|
fmt::detail::is_output_iterator<std::list<char>::iterator, char>::value));
|
||||||
|
EXPECT_FALSE((fmt::detail::is_output_iterator<std::list<char>::const_iterator,
|
||||||
|
char>::value));
|
||||||
|
EXPECT_FALSE((fmt::detail::is_output_iterator<uint32_pair, char>::value));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MemoryBufferTest, Ctor) {
|
TEST(MemoryBufferTest, Ctor) {
|
||||||
@ -720,13 +722,8 @@ TEST(FormatterTest, SpaceSign) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, SignNotTruncated) {
|
TEST(FormatterTest, SignNotTruncated) {
|
||||||
wchar_t format_str[] = {
|
wchar_t format_str[] = {L'{', L':',
|
||||||
L'{',
|
'+' | (1 << fmt::detail::num_bits<char>()), L'}', 0};
|
||||||
L':',
|
|
||||||
'+' | (1 << fmt::detail::num_bits<char>()),
|
|
||||||
L'}',
|
|
||||||
0
|
|
||||||
};
|
|
||||||
EXPECT_THROW(format(format_str, 42), format_error);
|
EXPECT_THROW(format(format_str, 42), format_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user