format_string-inl.h 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #ifndef FORMAT_STRING_INL_H_
  2. #error "Direct inclusion of this file is not allowed, include format_string.h"
  3. // For the sake of sane code completion.
  4. #include "format_string.h"
  5. #endif
  6. #include <algorithm>
  7. namespace NYT {
  8. ////////////////////////////////////////////////////////////////////////////////
  9. template <class... TArgs>
  10. template <class T>
  11. requires std::constructible_from<std::string_view, T>
  12. consteval TBasicFormatString<TArgs...>::TBasicFormatString(const T& fmt)
  13. : Format_(fmt)
  14. {
  15. CheckFormattability();
  16. #if !defined(YT_DISABLE_FORMAT_STATIC_ANALYSIS)
  17. std::tie(Markers, Escapes) = NDetail::TFormatAnalyser::AnalyzeFormat<std::remove_cvref_t<TArgs>...>(Format_);
  18. #else
  19. std::ranges::fill_n(std::ranges::begin(Escapes), 1, -1);
  20. if constexpr (sizeof...(TArgs) != 0) {
  21. std::ranges::fill_n(std::ranges::begin(Markers), 1, std::tuple{0, 0});
  22. }
  23. #endif
  24. }
  25. template <class... TArgs>
  26. TStringBuf TBasicFormatString<TArgs...>::Get() const noexcept
  27. {
  28. return {Format_};
  29. }
  30. template <class... TArgs>
  31. consteval void TBasicFormatString<TArgs...>::CheckFormattability()
  32. {
  33. #if !defined(NDEBUG) && !defined(YT_DISABLE_FORMAT_STATIC_ANALYSIS)
  34. using TTuple = std::tuple<std::remove_cvref_t<TArgs>...>;
  35. [] <size_t... Idx> (std::index_sequence<Idx...>) {
  36. ([] {
  37. if constexpr (!CFormattable<std::tuple_element_t<Idx, TTuple>>) {
  38. CrashCompilerClassIsNotFormattable<std::tuple_element_t<Idx, TTuple>>();
  39. }
  40. } (), ...);
  41. } (std::index_sequence_for<TArgs...>());
  42. #endif
  43. }
  44. template <class... TArgs>
  45. TBasicFormatString<TArgs...>::TBasicFormatString(TRuntimeFormat fmt)
  46. : Format_(fmt.Get())
  47. {
  48. std::ranges::fill_n(std::ranges::begin(Escapes), 1, -1);
  49. if constexpr (sizeof...(TArgs) != 0) {
  50. std::ranges::fill_n(std::ranges::begin(Markers), 1, std::tuple{0, 0});
  51. }
  52. // NB(arkady-e1ppa): StaticFormat performs the
  53. // formattability check of the args in a way
  54. // that provides more useful information
  55. // than a simple static_assert with conjunction.
  56. // Additionally, the latter doesn't work properly
  57. // for older clang version.
  58. static constexpr auto argsChecker = [] {
  59. CheckFormattability();
  60. return 42;
  61. } ();
  62. Y_UNUSED(argsChecker);
  63. }
  64. ////////////////////////////////////////////////////////////////////////////////
  65. } // namespace NYT