ranges.h 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. // Formatting library for C++ - range and tuple support
  2. //
  3. // Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
  4. // All rights reserved.
  5. //
  6. // For the license information refer to format.h.
  7. #ifndef FMT_RANGES_H_
  8. #define FMT_RANGES_H_
  9. #ifndef FMT_MODULE
  10. # include <initializer_list>
  11. # include <iterator>
  12. # include <string>
  13. # include <tuple>
  14. # include <type_traits>
  15. # include <utility>
  16. #endif
  17. #include "format.h"
  18. FMT_BEGIN_NAMESPACE
  19. FMT_EXPORT
  20. enum class range_format { disabled, map, set, sequence, string, debug_string };
  21. namespace detail {
  22. template <typename T> class is_map {
  23. template <typename U> static auto check(U*) -> typename U::mapped_type;
  24. template <typename> static void check(...);
  25. public:
  26. static constexpr const bool value =
  27. !std::is_void<decltype(check<T>(nullptr))>::value;
  28. };
  29. template <typename T> class is_set {
  30. template <typename U> static auto check(U*) -> typename U::key_type;
  31. template <typename> static void check(...);
  32. public:
  33. static constexpr const bool value =
  34. !std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
  35. };
  36. // C array overload
  37. template <typename T, std::size_t N>
  38. auto range_begin(const T (&arr)[N]) -> const T* {
  39. return arr;
  40. }
  41. template <typename T, std::size_t N>
  42. auto range_end(const T (&arr)[N]) -> const T* {
  43. return arr + N;
  44. }
  45. template <typename T, typename Enable = void>
  46. struct has_member_fn_begin_end_t : std::false_type {};
  47. template <typename T>
  48. struct has_member_fn_begin_end_t<T, void_t<decltype(*std::declval<T>().begin()),
  49. decltype(std::declval<T>().end())>>
  50. : std::true_type {};
  51. // Member function overloads.
  52. template <typename T>
  53. auto range_begin(T&& rng) -> decltype(static_cast<T&&>(rng).begin()) {
  54. return static_cast<T&&>(rng).begin();
  55. }
  56. template <typename T>
  57. auto range_end(T&& rng) -> decltype(static_cast<T&&>(rng).end()) {
  58. return static_cast<T&&>(rng).end();
  59. }
  60. // ADL overloads. Only participate in overload resolution if member functions
  61. // are not found.
  62. template <typename T>
  63. auto range_begin(T&& rng)
  64. -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
  65. decltype(begin(static_cast<T&&>(rng)))> {
  66. return begin(static_cast<T&&>(rng));
  67. }
  68. template <typename T>
  69. auto range_end(T&& rng) -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
  70. decltype(end(static_cast<T&&>(rng)))> {
  71. return end(static_cast<T&&>(rng));
  72. }
  73. template <typename T, typename Enable = void>
  74. struct has_const_begin_end : std::false_type {};
  75. template <typename T, typename Enable = void>
  76. struct has_mutable_begin_end : std::false_type {};
  77. template <typename T>
  78. struct has_const_begin_end<
  79. T, void_t<decltype(*detail::range_begin(
  80. std::declval<const remove_cvref_t<T>&>())),
  81. decltype(detail::range_end(
  82. std::declval<const remove_cvref_t<T>&>()))>>
  83. : std::true_type {};
  84. template <typename T>
  85. struct has_mutable_begin_end<
  86. T, void_t<decltype(*detail::range_begin(std::declval<T&>())),
  87. decltype(detail::range_end(std::declval<T&>())),
  88. // the extra int here is because older versions of MSVC don't
  89. // SFINAE properly unless there are distinct types
  90. int>> : std::true_type {};
  91. template <typename T, typename _ = void> struct is_range_ : std::false_type {};
  92. template <typename T>
  93. struct is_range_<T, void>
  94. : std::integral_constant<bool, (has_const_begin_end<T>::value ||
  95. has_mutable_begin_end<T>::value)> {};
  96. // tuple_size and tuple_element check.
  97. template <typename T> class is_tuple_like_ {
  98. template <typename U, typename V = typename std::remove_cv<U>::type>
  99. static auto check(U* p) -> decltype(std::tuple_size<V>::value, 0);
  100. template <typename> static void check(...);
  101. public:
  102. static constexpr const bool value =
  103. !std::is_void<decltype(check<T>(nullptr))>::value;
  104. };
  105. // Check for integer_sequence
  106. #if defined(__cpp_lib_integer_sequence) || FMT_MSC_VERSION >= 1900
  107. template <typename T, T... N>
  108. using integer_sequence = std::integer_sequence<T, N...>;
  109. template <size_t... N> using index_sequence = std::index_sequence<N...>;
  110. template <size_t N> using make_index_sequence = std::make_index_sequence<N>;
  111. #else
  112. template <typename T, T... N> struct integer_sequence {
  113. using value_type = T;
  114. static FMT_CONSTEXPR auto size() -> size_t { return sizeof...(N); }
  115. };
  116. template <size_t... N> using index_sequence = integer_sequence<size_t, N...>;
  117. template <typename T, size_t N, T... Ns>
  118. struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
  119. template <typename T, T... Ns>
  120. struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
  121. template <size_t N>
  122. using make_index_sequence = make_integer_sequence<size_t, N>;
  123. #endif
  124. template <typename T>
  125. using tuple_index_sequence = make_index_sequence<std::tuple_size<T>::value>;
  126. template <typename T, typename C, bool = is_tuple_like_<T>::value>
  127. class is_tuple_formattable_ {
  128. public:
  129. static constexpr const bool value = false;
  130. };
  131. template <typename T, typename C> class is_tuple_formattable_<T, C, true> {
  132. template <size_t... Is>
  133. static auto all_true(index_sequence<Is...>,
  134. integer_sequence<bool, (Is >= 0)...>) -> std::true_type;
  135. static auto all_true(...) -> std::false_type;
  136. template <size_t... Is>
  137. static auto check(index_sequence<Is...>) -> decltype(all_true(
  138. index_sequence<Is...>{},
  139. integer_sequence<bool,
  140. (is_formattable<typename std::tuple_element<Is, T>::type,
  141. C>::value)...>{}));
  142. public:
  143. static constexpr const bool value =
  144. decltype(check(tuple_index_sequence<T>{}))::value;
  145. };
  146. template <typename Tuple, typename F, size_t... Is>
  147. FMT_CONSTEXPR void for_each(index_sequence<Is...>, Tuple&& t, F&& f) {
  148. using std::get;
  149. // Using a free function get<Is>(Tuple) now.
  150. const int unused[] = {0, ((void)f(get<Is>(t)), 0)...};
  151. ignore_unused(unused);
  152. }
  153. template <typename Tuple, typename F>
  154. FMT_CONSTEXPR void for_each(Tuple&& t, F&& f) {
  155. for_each(tuple_index_sequence<remove_cvref_t<Tuple>>(),
  156. std::forward<Tuple>(t), std::forward<F>(f));
  157. }
  158. template <typename Tuple1, typename Tuple2, typename F, size_t... Is>
  159. void for_each2(index_sequence<Is...>, Tuple1&& t1, Tuple2&& t2, F&& f) {
  160. using std::get;
  161. const int unused[] = {0, ((void)f(get<Is>(t1), get<Is>(t2)), 0)...};
  162. ignore_unused(unused);
  163. }
  164. template <typename Tuple1, typename Tuple2, typename F>
  165. void for_each2(Tuple1&& t1, Tuple2&& t2, F&& f) {
  166. for_each2(tuple_index_sequence<remove_cvref_t<Tuple1>>(),
  167. std::forward<Tuple1>(t1), std::forward<Tuple2>(t2),
  168. std::forward<F>(f));
  169. }
  170. namespace tuple {
  171. // Workaround a bug in MSVC 2019 (v140).
  172. template <typename Char, typename... T>
  173. using result_t = std::tuple<formatter<remove_cvref_t<T>, Char>...>;
  174. using std::get;
  175. template <typename Tuple, typename Char, std::size_t... Is>
  176. auto get_formatters(index_sequence<Is...>)
  177. -> result_t<Char, decltype(get<Is>(std::declval<Tuple>()))...>;
  178. } // namespace tuple
  179. #if FMT_MSC_VERSION && FMT_MSC_VERSION < 1920
  180. // Older MSVC doesn't get the reference type correctly for arrays.
  181. template <typename R> struct range_reference_type_impl {
  182. using type = decltype(*detail::range_begin(std::declval<R&>()));
  183. };
  184. template <typename T, std::size_t N> struct range_reference_type_impl<T[N]> {
  185. using type = T&;
  186. };
  187. template <typename T>
  188. using range_reference_type = typename range_reference_type_impl<T>::type;
  189. #else
  190. template <typename Range>
  191. using range_reference_type =
  192. decltype(*detail::range_begin(std::declval<Range&>()));
  193. #endif
  194. // We don't use the Range's value_type for anything, but we do need the Range's
  195. // reference type, with cv-ref stripped.
  196. template <typename Range>
  197. using uncvref_type = remove_cvref_t<range_reference_type<Range>>;
  198. template <typename Formatter>
  199. FMT_CONSTEXPR auto maybe_set_debug_format(Formatter& f, bool set)
  200. -> decltype(f.set_debug_format(set)) {
  201. f.set_debug_format(set);
  202. }
  203. template <typename Formatter>
  204. FMT_CONSTEXPR void maybe_set_debug_format(Formatter&, ...) {}
  205. template <typename T>
  206. struct range_format_kind_
  207. : std::integral_constant<range_format,
  208. std::is_same<uncvref_type<T>, T>::value
  209. ? range_format::disabled
  210. : is_map<T>::value ? range_format::map
  211. : is_set<T>::value ? range_format::set
  212. : range_format::sequence> {};
  213. template <range_format K>
  214. using range_format_constant = std::integral_constant<range_format, K>;
  215. // These are not generic lambdas for compatibility with C++11.
  216. template <typename Char> struct parse_empty_specs {
  217. template <typename Formatter> FMT_CONSTEXPR void operator()(Formatter& f) {
  218. f.parse(ctx);
  219. detail::maybe_set_debug_format(f, true);
  220. }
  221. parse_context<Char>& ctx;
  222. };
  223. template <typename FormatContext> struct format_tuple_element {
  224. using char_type = typename FormatContext::char_type;
  225. template <typename T>
  226. void operator()(const formatter<T, char_type>& f, const T& v) {
  227. if (i > 0) ctx.advance_to(detail::copy<char_type>(separator, ctx.out()));
  228. ctx.advance_to(f.format(v, ctx));
  229. ++i;
  230. }
  231. int i;
  232. FormatContext& ctx;
  233. basic_string_view<char_type> separator;
  234. };
  235. } // namespace detail
  236. template <typename T> struct is_tuple_like {
  237. static constexpr const bool value =
  238. detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
  239. };
  240. template <typename T, typename C> struct is_tuple_formattable {
  241. static constexpr const bool value =
  242. detail::is_tuple_formattable_<T, C>::value;
  243. };
  244. template <typename Tuple, typename Char>
  245. struct formatter<Tuple, Char,
  246. enable_if_t<fmt::is_tuple_like<Tuple>::value &&
  247. fmt::is_tuple_formattable<Tuple, Char>::value>> {
  248. private:
  249. decltype(detail::tuple::get_formatters<Tuple, Char>(
  250. detail::tuple_index_sequence<Tuple>())) formatters_;
  251. basic_string_view<Char> separator_ = detail::string_literal<Char, ',', ' '>{};
  252. basic_string_view<Char> opening_bracket_ =
  253. detail::string_literal<Char, '('>{};
  254. basic_string_view<Char> closing_bracket_ =
  255. detail::string_literal<Char, ')'>{};
  256. public:
  257. FMT_CONSTEXPR formatter() {}
  258. FMT_CONSTEXPR void set_separator(basic_string_view<Char> sep) {
  259. separator_ = sep;
  260. }
  261. FMT_CONSTEXPR void set_brackets(basic_string_view<Char> open,
  262. basic_string_view<Char> close) {
  263. opening_bracket_ = open;
  264. closing_bracket_ = close;
  265. }
  266. FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
  267. auto it = ctx.begin();
  268. auto end = ctx.end();
  269. if (it != end && detail::to_ascii(*it) == 'n') {
  270. ++it;
  271. set_brackets({}, {});
  272. set_separator({});
  273. }
  274. if (it != end && *it != '}') report_error("invalid format specifier");
  275. ctx.advance_to(it);
  276. detail::for_each(formatters_, detail::parse_empty_specs<Char>{ctx});
  277. return it;
  278. }
  279. template <typename FormatContext>
  280. auto format(const Tuple& value, FormatContext& ctx) const
  281. -> decltype(ctx.out()) {
  282. ctx.advance_to(detail::copy<Char>(opening_bracket_, ctx.out()));
  283. detail::for_each2(
  284. formatters_, value,
  285. detail::format_tuple_element<FormatContext>{0, ctx, separator_});
  286. return detail::copy<Char>(closing_bracket_, ctx.out());
  287. }
  288. };
  289. template <typename T, typename Char> struct is_range {
  290. static constexpr const bool value =
  291. detail::is_range_<T>::value && !detail::has_to_string_view<T>::value;
  292. };
  293. namespace detail {
  294. template <typename Char, typename Element>
  295. using range_formatter_type = formatter<remove_cvref_t<Element>, Char>;
  296. template <typename R>
  297. using maybe_const_range =
  298. conditional_t<has_const_begin_end<R>::value, const R, R>;
  299. template <typename R, typename Char>
  300. struct is_formattable_delayed
  301. : is_formattable<uncvref_type<maybe_const_range<R>>, Char> {};
  302. } // namespace detail
  303. template <typename...> struct conjunction : std::true_type {};
  304. template <typename P> struct conjunction<P> : P {};
  305. template <typename P1, typename... Pn>
  306. struct conjunction<P1, Pn...>
  307. : conditional_t<bool(P1::value), conjunction<Pn...>, P1> {};
  308. template <typename T, typename Char, typename Enable = void>
  309. struct range_formatter;
  310. template <typename T, typename Char>
  311. struct range_formatter<
  312. T, Char,
  313. enable_if_t<conjunction<std::is_same<T, remove_cvref_t<T>>,
  314. is_formattable<T, Char>>::value>> {
  315. private:
  316. detail::range_formatter_type<Char, T> underlying_;
  317. basic_string_view<Char> separator_ = detail::string_literal<Char, ',', ' '>{};
  318. basic_string_view<Char> opening_bracket_ =
  319. detail::string_literal<Char, '['>{};
  320. basic_string_view<Char> closing_bracket_ =
  321. detail::string_literal<Char, ']'>{};
  322. bool is_debug = false;
  323. template <typename Output, typename It, typename Sentinel, typename U = T,
  324. FMT_ENABLE_IF(std::is_same<U, Char>::value)>
  325. auto write_debug_string(Output& out, It it, Sentinel end) const -> Output {
  326. auto buf = basic_memory_buffer<Char>();
  327. for (; it != end; ++it) buf.push_back(*it);
  328. auto specs = format_specs();
  329. specs.set_type(presentation_type::debug);
  330. return detail::write<Char>(
  331. out, basic_string_view<Char>(buf.data(), buf.size()), specs);
  332. }
  333. template <typename Output, typename It, typename Sentinel, typename U = T,
  334. FMT_ENABLE_IF(!std::is_same<U, Char>::value)>
  335. auto write_debug_string(Output& out, It, Sentinel) const -> Output {
  336. return out;
  337. }
  338. public:
  339. FMT_CONSTEXPR range_formatter() {}
  340. FMT_CONSTEXPR auto underlying() -> detail::range_formatter_type<Char, T>& {
  341. return underlying_;
  342. }
  343. FMT_CONSTEXPR void set_separator(basic_string_view<Char> sep) {
  344. separator_ = sep;
  345. }
  346. FMT_CONSTEXPR void set_brackets(basic_string_view<Char> open,
  347. basic_string_view<Char> close) {
  348. opening_bracket_ = open;
  349. closing_bracket_ = close;
  350. }
  351. FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
  352. auto it = ctx.begin();
  353. auto end = ctx.end();
  354. detail::maybe_set_debug_format(underlying_, true);
  355. if (it == end) return underlying_.parse(ctx);
  356. switch (detail::to_ascii(*it)) {
  357. case 'n':
  358. set_brackets({}, {});
  359. ++it;
  360. break;
  361. case '?':
  362. is_debug = true;
  363. set_brackets({}, {});
  364. ++it;
  365. if (it == end || *it != 's') report_error("invalid format specifier");
  366. FMT_FALLTHROUGH;
  367. case 's':
  368. if (!std::is_same<T, Char>::value)
  369. report_error("invalid format specifier");
  370. if (!is_debug) {
  371. set_brackets(detail::string_literal<Char, '"'>{},
  372. detail::string_literal<Char, '"'>{});
  373. set_separator({});
  374. detail::maybe_set_debug_format(underlying_, false);
  375. }
  376. ++it;
  377. return it;
  378. }
  379. if (it != end && *it != '}') {
  380. if (*it != ':') report_error("invalid format specifier");
  381. detail::maybe_set_debug_format(underlying_, false);
  382. ++it;
  383. }
  384. ctx.advance_to(it);
  385. return underlying_.parse(ctx);
  386. }
  387. template <typename R, typename FormatContext>
  388. auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) {
  389. auto out = ctx.out();
  390. auto it = detail::range_begin(range);
  391. auto end = detail::range_end(range);
  392. if (is_debug) return write_debug_string(out, std::move(it), end);
  393. out = detail::copy<Char>(opening_bracket_, out);
  394. int i = 0;
  395. for (; it != end; ++it) {
  396. if (i > 0) out = detail::copy<Char>(separator_, out);
  397. ctx.advance_to(out);
  398. auto&& item = *it; // Need an lvalue
  399. out = underlying_.format(item, ctx);
  400. ++i;
  401. }
  402. out = detail::copy<Char>(closing_bracket_, out);
  403. return out;
  404. }
  405. };
  406. FMT_EXPORT
  407. template <typename T, typename Char, typename Enable = void>
  408. struct range_format_kind
  409. : conditional_t<
  410. is_range<T, Char>::value, detail::range_format_kind_<T>,
  411. std::integral_constant<range_format, range_format::disabled>> {};
  412. template <typename R, typename Char>
  413. struct formatter<
  414. R, Char,
  415. enable_if_t<conjunction<
  416. bool_constant<
  417. range_format_kind<R, Char>::value != range_format::disabled &&
  418. range_format_kind<R, Char>::value != range_format::map &&
  419. range_format_kind<R, Char>::value != range_format::string &&
  420. range_format_kind<R, Char>::value != range_format::debug_string>,
  421. detail::is_formattable_delayed<R, Char>>::value>> {
  422. private:
  423. using range_type = detail::maybe_const_range<R>;
  424. range_formatter<detail::uncvref_type<range_type>, Char> range_formatter_;
  425. public:
  426. using nonlocking = void;
  427. FMT_CONSTEXPR formatter() {
  428. if (detail::const_check(range_format_kind<R, Char>::value !=
  429. range_format::set))
  430. return;
  431. range_formatter_.set_brackets(detail::string_literal<Char, '{'>{},
  432. detail::string_literal<Char, '}'>{});
  433. }
  434. FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
  435. return range_formatter_.parse(ctx);
  436. }
  437. template <typename FormatContext>
  438. auto format(range_type& range, FormatContext& ctx) const
  439. -> decltype(ctx.out()) {
  440. return range_formatter_.format(range, ctx);
  441. }
  442. };
  443. // A map formatter.
  444. template <typename R, typename Char>
  445. struct formatter<
  446. R, Char,
  447. enable_if_t<range_format_kind<R, Char>::value == range_format::map>> {
  448. private:
  449. using map_type = detail::maybe_const_range<R>;
  450. using element_type = detail::uncvref_type<map_type>;
  451. decltype(detail::tuple::get_formatters<element_type, Char>(
  452. detail::tuple_index_sequence<element_type>())) formatters_;
  453. bool no_delimiters_ = false;
  454. public:
  455. FMT_CONSTEXPR formatter() {}
  456. FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
  457. auto it = ctx.begin();
  458. auto end = ctx.end();
  459. if (it != end) {
  460. if (detail::to_ascii(*it) == 'n') {
  461. no_delimiters_ = true;
  462. ++it;
  463. }
  464. if (it != end && *it != '}') {
  465. if (*it != ':') report_error("invalid format specifier");
  466. ++it;
  467. }
  468. ctx.advance_to(it);
  469. }
  470. detail::for_each(formatters_, detail::parse_empty_specs<Char>{ctx});
  471. return it;
  472. }
  473. template <typename FormatContext>
  474. auto format(map_type& map, FormatContext& ctx) const -> decltype(ctx.out()) {
  475. auto out = ctx.out();
  476. basic_string_view<Char> open = detail::string_literal<Char, '{'>{};
  477. if (!no_delimiters_) out = detail::copy<Char>(open, out);
  478. int i = 0;
  479. basic_string_view<Char> sep = detail::string_literal<Char, ',', ' '>{};
  480. for (auto&& value : map) {
  481. if (i > 0) out = detail::copy<Char>(sep, out);
  482. ctx.advance_to(out);
  483. detail::for_each2(formatters_, value,
  484. detail::format_tuple_element<FormatContext>{
  485. 0, ctx, detail::string_literal<Char, ':', ' '>{}});
  486. ++i;
  487. }
  488. basic_string_view<Char> close = detail::string_literal<Char, '}'>{};
  489. if (!no_delimiters_) out = detail::copy<Char>(close, out);
  490. return out;
  491. }
  492. };
  493. // A (debug_)string formatter.
  494. template <typename R, typename Char>
  495. struct formatter<
  496. R, Char,
  497. enable_if_t<range_format_kind<R, Char>::value == range_format::string ||
  498. range_format_kind<R, Char>::value ==
  499. range_format::debug_string>> {
  500. private:
  501. using range_type = detail::maybe_const_range<R>;
  502. using string_type =
  503. conditional_t<std::is_constructible<
  504. detail::std_string_view<Char>,
  505. decltype(detail::range_begin(std::declval<R>())),
  506. decltype(detail::range_end(std::declval<R>()))>::value,
  507. detail::std_string_view<Char>, std::basic_string<Char>>;
  508. formatter<string_type, Char> underlying_;
  509. public:
  510. FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
  511. return underlying_.parse(ctx);
  512. }
  513. template <typename FormatContext>
  514. auto format(range_type& range, FormatContext& ctx) const
  515. -> decltype(ctx.out()) {
  516. auto out = ctx.out();
  517. if (detail::const_check(range_format_kind<R, Char>::value ==
  518. range_format::debug_string))
  519. *out++ = '"';
  520. out = underlying_.format(
  521. string_type{detail::range_begin(range), detail::range_end(range)}, ctx);
  522. if (detail::const_check(range_format_kind<R, Char>::value ==
  523. range_format::debug_string))
  524. *out++ = '"';
  525. return out;
  526. }
  527. };
  528. template <typename It, typename Sentinel, typename Char = char>
  529. struct join_view : detail::view {
  530. It begin;
  531. Sentinel end;
  532. basic_string_view<Char> sep;
  533. join_view(It b, Sentinel e, basic_string_view<Char> s)
  534. : begin(std::move(b)), end(e), sep(s) {}
  535. };
  536. template <typename It, typename Sentinel, typename Char>
  537. struct formatter<join_view<It, Sentinel, Char>, Char> {
  538. private:
  539. using value_type =
  540. #ifdef __cpp_lib_ranges
  541. std::iter_value_t<It>;
  542. #else
  543. typename std::iterator_traits<It>::value_type;
  544. #endif
  545. formatter<remove_cvref_t<value_type>, Char> value_formatter_;
  546. using view = conditional_t<std::is_copy_constructible<It>::value,
  547. const join_view<It, Sentinel, Char>,
  548. join_view<It, Sentinel, Char>>;
  549. public:
  550. using nonlocking = void;
  551. FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
  552. return value_formatter_.parse(ctx);
  553. }
  554. template <typename FormatContext>
  555. auto format(view& value, FormatContext& ctx) const -> decltype(ctx.out()) {
  556. using iter =
  557. conditional_t<std::is_copy_constructible<view>::value, It, It&>;
  558. iter it = value.begin;
  559. auto out = ctx.out();
  560. if (it == value.end) return out;
  561. out = value_formatter_.format(*it, ctx);
  562. ++it;
  563. while (it != value.end) {
  564. out = detail::copy<Char>(value.sep.begin(), value.sep.end(), out);
  565. ctx.advance_to(out);
  566. out = value_formatter_.format(*it, ctx);
  567. ++it;
  568. }
  569. return out;
  570. }
  571. };
  572. template <typename Char, typename Tuple> struct tuple_join_view : detail::view {
  573. const Tuple& tuple;
  574. basic_string_view<Char> sep;
  575. tuple_join_view(const Tuple& t, basic_string_view<Char> s)
  576. : tuple(t), sep{s} {}
  577. };
  578. // Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers
  579. // support in tuple_join. It is disabled by default because of issues with
  580. // the dynamic width and precision.
  581. #ifndef FMT_TUPLE_JOIN_SPECIFIERS
  582. # define FMT_TUPLE_JOIN_SPECIFIERS 0
  583. #endif
  584. template <typename Char, typename Tuple>
  585. struct formatter<tuple_join_view<Char, Tuple>, Char,
  586. enable_if_t<is_tuple_like<Tuple>::value>> {
  587. FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
  588. return do_parse(ctx, std::tuple_size<Tuple>());
  589. }
  590. template <typename FormatContext>
  591. auto format(const tuple_join_view<Char, Tuple>& value,
  592. FormatContext& ctx) const -> typename FormatContext::iterator {
  593. return do_format(value, ctx, std::tuple_size<Tuple>());
  594. }
  595. private:
  596. decltype(detail::tuple::get_formatters<Tuple, Char>(
  597. detail::tuple_index_sequence<Tuple>())) formatters_;
  598. FMT_CONSTEXPR auto do_parse(parse_context<Char>& ctx,
  599. std::integral_constant<size_t, 0>)
  600. -> const Char* {
  601. return ctx.begin();
  602. }
  603. template <size_t N>
  604. FMT_CONSTEXPR auto do_parse(parse_context<Char>& ctx,
  605. std::integral_constant<size_t, N>)
  606. -> const Char* {
  607. auto end = ctx.begin();
  608. #if FMT_TUPLE_JOIN_SPECIFIERS
  609. end = std::get<std::tuple_size<Tuple>::value - N>(formatters_).parse(ctx);
  610. if (N > 1) {
  611. auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
  612. if (end != end1)
  613. report_error("incompatible format specs for tuple elements");
  614. }
  615. #endif
  616. return end;
  617. }
  618. template <typename FormatContext>
  619. auto do_format(const tuple_join_view<Char, Tuple>&, FormatContext& ctx,
  620. std::integral_constant<size_t, 0>) const ->
  621. typename FormatContext::iterator {
  622. return ctx.out();
  623. }
  624. template <typename FormatContext, size_t N>
  625. auto do_format(const tuple_join_view<Char, Tuple>& value, FormatContext& ctx,
  626. std::integral_constant<size_t, N>) const ->
  627. typename FormatContext::iterator {
  628. using std::get;
  629. auto out =
  630. std::get<std::tuple_size<Tuple>::value - N>(formatters_)
  631. .format(get<std::tuple_size<Tuple>::value - N>(value.tuple), ctx);
  632. if (N <= 1) return out;
  633. out = detail::copy<Char>(value.sep, out);
  634. ctx.advance_to(out);
  635. return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
  636. }
  637. };
  638. namespace detail {
  639. // Check if T has an interface like a container adaptor (e.g. std::stack,
  640. // std::queue, std::priority_queue).
  641. template <typename T> class is_container_adaptor_like {
  642. template <typename U> static auto check(U* p) -> typename U::container_type;
  643. template <typename> static void check(...);
  644. public:
  645. static constexpr const bool value =
  646. !std::is_void<decltype(check<T>(nullptr))>::value;
  647. };
  648. template <typename Container> struct all {
  649. const Container& c;
  650. auto begin() const -> typename Container::const_iterator { return c.begin(); }
  651. auto end() const -> typename Container::const_iterator { return c.end(); }
  652. };
  653. } // namespace detail
  654. template <typename T, typename Char>
  655. struct formatter<
  656. T, Char,
  657. enable_if_t<conjunction<detail::is_container_adaptor_like<T>,
  658. bool_constant<range_format_kind<T, Char>::value ==
  659. range_format::disabled>>::value>>
  660. : formatter<detail::all<typename T::container_type>, Char> {
  661. using all = detail::all<typename T::container_type>;
  662. template <typename FormatContext>
  663. auto format(const T& t, FormatContext& ctx) const -> decltype(ctx.out()) {
  664. struct getter : T {
  665. static auto get(const T& t) -> all {
  666. return {t.*(&getter::c)}; // Access c through the derived class.
  667. }
  668. };
  669. return formatter<all>::format(getter::get(t), ctx);
  670. }
  671. };
  672. FMT_BEGIN_EXPORT
  673. /// Returns a view that formats the iterator range `[begin, end)` with elements
  674. /// separated by `sep`.
  675. template <typename It, typename Sentinel>
  676. auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
  677. return {std::move(begin), end, sep};
  678. }
  679. /**
  680. * Returns a view that formats `range` with elements separated by `sep`.
  681. *
  682. * **Example**:
  683. *
  684. * auto v = std::vector<int>{1, 2, 3};
  685. * fmt::print("{}", fmt::join(v, ", "));
  686. * // Output: 1, 2, 3
  687. *
  688. * `fmt::join` applies passed format specifiers to the range elements:
  689. *
  690. * fmt::print("{:02}", fmt::join(v, ", "));
  691. * // Output: 01, 02, 03
  692. */
  693. template <typename Range, FMT_ENABLE_IF(!is_tuple_like<Range>::value)>
  694. auto join(Range&& r, string_view sep)
  695. -> join_view<decltype(detail::range_begin(r)),
  696. decltype(detail::range_end(r))> {
  697. return {detail::range_begin(r), detail::range_end(r), sep};
  698. }
  699. /**
  700. * Returns an object that formats `std::tuple` with elements separated by `sep`.
  701. *
  702. * **Example**:
  703. *
  704. * auto t = std::tuple<int, char>{1, 'a'};
  705. * fmt::print("{}", fmt::join(t, ", "));
  706. * // Output: 1, a
  707. */
  708. template <typename Tuple, FMT_ENABLE_IF(is_tuple_like<Tuple>::value)>
  709. FMT_CONSTEXPR auto join(const Tuple& tuple, string_view sep)
  710. -> tuple_join_view<char, Tuple> {
  711. return {tuple, sep};
  712. }
  713. /**
  714. * Returns an object that formats `std::initializer_list` with elements
  715. * separated by `sep`.
  716. *
  717. * **Example**:
  718. *
  719. * fmt::print("{}", fmt::join({1, 2, 3}, ", "));
  720. * // Output: "1, 2, 3"
  721. */
  722. template <typename T>
  723. auto join(std::initializer_list<T> list, string_view sep)
  724. -> join_view<const T*, const T*> {
  725. return join(std::begin(list), std::end(list), sep);
  726. }
  727. FMT_END_EXPORT
  728. FMT_END_NAMESPACE
  729. #endif // FMT_RANGES_H_