ranges.h 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  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<conjunction<
  448. bool_constant<range_format_kind<R, Char>::value == range_format::map>,
  449. detail::is_formattable_delayed<R, Char>>::value>> {
  450. private:
  451. using map_type = detail::maybe_const_range<R>;
  452. using element_type = detail::uncvref_type<map_type>;
  453. decltype(detail::tuple::get_formatters<element_type, Char>(
  454. detail::tuple_index_sequence<element_type>())) formatters_;
  455. bool no_delimiters_ = false;
  456. public:
  457. FMT_CONSTEXPR formatter() {}
  458. FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
  459. auto it = ctx.begin();
  460. auto end = ctx.end();
  461. if (it != end) {
  462. if (detail::to_ascii(*it) == 'n') {
  463. no_delimiters_ = true;
  464. ++it;
  465. }
  466. if (it != end && *it != '}') {
  467. if (*it != ':') report_error("invalid format specifier");
  468. ++it;
  469. }
  470. ctx.advance_to(it);
  471. }
  472. detail::for_each(formatters_, detail::parse_empty_specs<Char>{ctx});
  473. return it;
  474. }
  475. template <typename FormatContext>
  476. auto format(map_type& map, FormatContext& ctx) const -> decltype(ctx.out()) {
  477. auto out = ctx.out();
  478. basic_string_view<Char> open = detail::string_literal<Char, '{'>{};
  479. if (!no_delimiters_) out = detail::copy<Char>(open, out);
  480. int i = 0;
  481. basic_string_view<Char> sep = detail::string_literal<Char, ',', ' '>{};
  482. for (auto&& value : map) {
  483. if (i > 0) out = detail::copy<Char>(sep, out);
  484. ctx.advance_to(out);
  485. detail::for_each2(formatters_, value,
  486. detail::format_tuple_element<FormatContext>{
  487. 0, ctx, detail::string_literal<Char, ':', ' '>{}});
  488. ++i;
  489. }
  490. basic_string_view<Char> close = detail::string_literal<Char, '}'>{};
  491. if (!no_delimiters_) out = detail::copy<Char>(close, out);
  492. return out;
  493. }
  494. };
  495. // A (debug_)string formatter.
  496. template <typename R, typename Char>
  497. struct formatter<
  498. R, Char,
  499. enable_if_t<range_format_kind<R, Char>::value == range_format::string ||
  500. range_format_kind<R, Char>::value ==
  501. range_format::debug_string>> {
  502. private:
  503. using range_type = detail::maybe_const_range<R>;
  504. using string_type =
  505. conditional_t<std::is_constructible<
  506. detail::std_string_view<Char>,
  507. decltype(detail::range_begin(std::declval<R>())),
  508. decltype(detail::range_end(std::declval<R>()))>::value,
  509. detail::std_string_view<Char>, std::basic_string<Char>>;
  510. formatter<string_type, Char> underlying_;
  511. public:
  512. FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
  513. return underlying_.parse(ctx);
  514. }
  515. template <typename FormatContext>
  516. auto format(range_type& range, FormatContext& ctx) const
  517. -> decltype(ctx.out()) {
  518. auto out = ctx.out();
  519. if (detail::const_check(range_format_kind<R, Char>::value ==
  520. range_format::debug_string))
  521. *out++ = '"';
  522. out = underlying_.format(
  523. string_type{detail::range_begin(range), detail::range_end(range)}, ctx);
  524. if (detail::const_check(range_format_kind<R, Char>::value ==
  525. range_format::debug_string))
  526. *out++ = '"';
  527. return out;
  528. }
  529. };
  530. template <typename It, typename Sentinel, typename Char = char>
  531. struct join_view : detail::view {
  532. It begin;
  533. Sentinel end;
  534. basic_string_view<Char> sep;
  535. join_view(It b, Sentinel e, basic_string_view<Char> s)
  536. : begin(std::move(b)), end(e), sep(s) {}
  537. };
  538. template <typename It, typename Sentinel, typename Char>
  539. struct formatter<join_view<It, Sentinel, Char>, Char> {
  540. private:
  541. using value_type =
  542. #ifdef __cpp_lib_ranges
  543. std::iter_value_t<It>;
  544. #else
  545. typename std::iterator_traits<It>::value_type;
  546. #endif
  547. formatter<remove_cvref_t<value_type>, Char> value_formatter_;
  548. using view = conditional_t<std::is_copy_constructible<It>::value,
  549. const join_view<It, Sentinel, Char>,
  550. join_view<It, Sentinel, Char>>;
  551. public:
  552. using nonlocking = void;
  553. FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
  554. return value_formatter_.parse(ctx);
  555. }
  556. template <typename FormatContext>
  557. auto format(view& value, FormatContext& ctx) const -> decltype(ctx.out()) {
  558. using iter =
  559. conditional_t<std::is_copy_constructible<view>::value, It, It&>;
  560. iter it = value.begin;
  561. auto out = ctx.out();
  562. if (it == value.end) return out;
  563. out = value_formatter_.format(*it, ctx);
  564. ++it;
  565. while (it != value.end) {
  566. out = detail::copy<Char>(value.sep.begin(), value.sep.end(), out);
  567. ctx.advance_to(out);
  568. out = value_formatter_.format(*it, ctx);
  569. ++it;
  570. }
  571. return out;
  572. }
  573. };
  574. template <typename Char, typename Tuple> struct tuple_join_view : detail::view {
  575. const Tuple& tuple;
  576. basic_string_view<Char> sep;
  577. tuple_join_view(const Tuple& t, basic_string_view<Char> s)
  578. : tuple(t), sep{s} {}
  579. };
  580. // Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers
  581. // support in tuple_join. It is disabled by default because of issues with
  582. // the dynamic width and precision.
  583. #ifndef FMT_TUPLE_JOIN_SPECIFIERS
  584. # define FMT_TUPLE_JOIN_SPECIFIERS 0
  585. #endif
  586. template <typename Char, typename Tuple>
  587. struct formatter<tuple_join_view<Char, Tuple>, Char,
  588. enable_if_t<is_tuple_like<Tuple>::value>> {
  589. FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
  590. return do_parse(ctx, std::tuple_size<Tuple>());
  591. }
  592. template <typename FormatContext>
  593. auto format(const tuple_join_view<Char, Tuple>& value,
  594. FormatContext& ctx) const -> typename FormatContext::iterator {
  595. return do_format(value, ctx, std::tuple_size<Tuple>());
  596. }
  597. private:
  598. decltype(detail::tuple::get_formatters<Tuple, Char>(
  599. detail::tuple_index_sequence<Tuple>())) formatters_;
  600. FMT_CONSTEXPR auto do_parse(parse_context<Char>& ctx,
  601. std::integral_constant<size_t, 0>)
  602. -> const Char* {
  603. return ctx.begin();
  604. }
  605. template <size_t N>
  606. FMT_CONSTEXPR auto do_parse(parse_context<Char>& ctx,
  607. std::integral_constant<size_t, N>)
  608. -> const Char* {
  609. auto end = ctx.begin();
  610. #if FMT_TUPLE_JOIN_SPECIFIERS
  611. end = std::get<std::tuple_size<Tuple>::value - N>(formatters_).parse(ctx);
  612. if (N > 1) {
  613. auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
  614. if (end != end1)
  615. report_error("incompatible format specs for tuple elements");
  616. }
  617. #endif
  618. return end;
  619. }
  620. template <typename FormatContext>
  621. auto do_format(const tuple_join_view<Char, Tuple>&, FormatContext& ctx,
  622. std::integral_constant<size_t, 0>) const ->
  623. typename FormatContext::iterator {
  624. return ctx.out();
  625. }
  626. template <typename FormatContext, size_t N>
  627. auto do_format(const tuple_join_view<Char, Tuple>& value, FormatContext& ctx,
  628. std::integral_constant<size_t, N>) const ->
  629. typename FormatContext::iterator {
  630. using std::get;
  631. auto out =
  632. std::get<std::tuple_size<Tuple>::value - N>(formatters_)
  633. .format(get<std::tuple_size<Tuple>::value - N>(value.tuple), ctx);
  634. if (N <= 1) return out;
  635. out = detail::copy<Char>(value.sep, out);
  636. ctx.advance_to(out);
  637. return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
  638. }
  639. };
  640. namespace detail {
  641. // Check if T has an interface like a container adaptor (e.g. std::stack,
  642. // std::queue, std::priority_queue).
  643. template <typename T> class is_container_adaptor_like {
  644. template <typename U> static auto check(U* p) -> typename U::container_type;
  645. template <typename> static void check(...);
  646. public:
  647. static constexpr const bool value =
  648. !std::is_void<decltype(check<T>(nullptr))>::value;
  649. };
  650. template <typename Container> struct all {
  651. const Container& c;
  652. auto begin() const -> typename Container::const_iterator { return c.begin(); }
  653. auto end() const -> typename Container::const_iterator { return c.end(); }
  654. };
  655. } // namespace detail
  656. template <typename T, typename Char>
  657. struct formatter<
  658. T, Char,
  659. enable_if_t<conjunction<detail::is_container_adaptor_like<T>,
  660. bool_constant<range_format_kind<T, Char>::value ==
  661. range_format::disabled>>::value>>
  662. : formatter<detail::all<typename T::container_type>, Char> {
  663. using all = detail::all<typename T::container_type>;
  664. template <typename FormatContext>
  665. auto format(const T& value, FormatContext& ctx) const -> decltype(ctx.out()) {
  666. struct getter : T {
  667. static auto get(const T& v) -> all {
  668. return {v.*(&getter::c)}; // Access c through the derived class.
  669. }
  670. };
  671. return formatter<all>::format(getter::get(value), ctx);
  672. }
  673. };
  674. FMT_BEGIN_EXPORT
  675. /// Returns a view that formats the iterator range `[begin, end)` with elements
  676. /// separated by `sep`.
  677. template <typename It, typename Sentinel>
  678. auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
  679. return {std::move(begin), end, sep};
  680. }
  681. /**
  682. * Returns a view that formats `range` with elements separated by `sep`.
  683. *
  684. * **Example**:
  685. *
  686. * auto v = std::vector<int>{1, 2, 3};
  687. * fmt::print("{}", fmt::join(v, ", "));
  688. * // Output: 1, 2, 3
  689. *
  690. * `fmt::join` applies passed format specifiers to the range elements:
  691. *
  692. * fmt::print("{:02}", fmt::join(v, ", "));
  693. * // Output: 01, 02, 03
  694. */
  695. template <typename Range, FMT_ENABLE_IF(!is_tuple_like<Range>::value)>
  696. auto join(Range&& r, string_view sep)
  697. -> join_view<decltype(detail::range_begin(r)),
  698. decltype(detail::range_end(r))> {
  699. return {detail::range_begin(r), detail::range_end(r), sep};
  700. }
  701. /**
  702. * Returns an object that formats `std::tuple` with elements separated by `sep`.
  703. *
  704. * **Example**:
  705. *
  706. * auto t = std::tuple<int, char>{1, 'a'};
  707. * fmt::print("{}", fmt::join(t, ", "));
  708. * // Output: 1, a
  709. */
  710. template <typename Tuple, FMT_ENABLE_IF(is_tuple_like<Tuple>::value)>
  711. FMT_CONSTEXPR auto join(const Tuple& tuple, string_view sep)
  712. -> tuple_join_view<char, Tuple> {
  713. return {tuple, sep};
  714. }
  715. /**
  716. * Returns an object that formats `std::initializer_list` with elements
  717. * separated by `sep`.
  718. *
  719. * **Example**:
  720. *
  721. * fmt::print("{}", fmt::join({1, 2, 3}, ", "));
  722. * // Output: "1, 2, 3"
  723. */
  724. template <typename T>
  725. auto join(std::initializer_list<T> list, string_view sep)
  726. -> join_view<const T*, const T*> {
  727. return join(std::begin(list), std::end(list), sep);
  728. }
  729. FMT_END_EXPORT
  730. FMT_END_NAMESPACE
  731. #endif // FMT_RANGES_H_