ranges.h 28 KB

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