Advertisement
gt22

Untitled

Jul 4th, 2020
1,084
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.23 KB | None | 0 0
  1. #include <cstddef>  // std::size_t
  2. #include <string>  // std::string
  3. #include <charconv> // std::to_chars
  4. #include <cmath> // std::ceil
  5. #include <iterator>
  6. #include <type_traits>
  7. #include <cassert>
  8.  
  9. #if __cplusplus < 201703L
  10. #error At least C++17 is required
  11. #endif
  12.  
  13. namespace format {
  14.  
  15.     template<typename, typename = void>
  16.     struct FormatHelper;
  17.  
  18.     namespace validator {
  19.  
  20.         template<typename T, size_t = sizeof(FormatHelper<T>)>
  21.         constexpr bool has_format_helper(std::nullptr_t) {
  22.             return true;
  23.         }
  24.  
  25.         template<typename T>
  26.         constexpr bool has_format_helper(...) {
  27.             return false;
  28.         }
  29.  
  30.         template<typename T>
  31.         constexpr bool has_format_helper_v = has_format_helper<T>(nullptr);
  32.  
  33.         template<typename T, typename = std::enable_if_t<
  34.                 std::is_same_v<std::string,
  35.                         decltype(std::declval<const T&>().format())>>>
  36.         constexpr bool has_format(std::nullptr_t) {
  37.             return true;
  38.         }
  39.  
  40.         template<typename T>
  41.         constexpr bool has_format(...) {
  42.             return false;
  43.         }
  44.  
  45.         template<typename T>
  46.         constexpr bool has_format_v = has_format<T>(nullptr);
  47.  
  48.     }
  49.  
  50.     template<>
  51.     struct FormatHelper<bool> {
  52.         explicit FormatHelper(bool b) : val(b) {}
  53.  
  54.         std::size_t estimate_size() const {
  55.             return val ? 4 : 5;
  56.         }
  57.  
  58.         void append_to(std::string& s) const {
  59.             s += val ? "true" : "false";
  60.         }
  61.  
  62.     private:
  63.         bool val;
  64.     };
  65.  
  66.     template<typename T>
  67.     struct FormatHelper<std::vector<T>, std::enable_if_t<validator::has_format_helper_v<T>>> {
  68.  
  69.         explicit FormatHelper(const std::vector<T>& val) : vec(val) {
  70.             fmt.reserve(val.size());
  71.             for (const auto& v : val) {
  72.                 fmt.emplace_back(v);
  73.             }
  74.         }
  75.  
  76.         std::size_t estimate_size() const {
  77.             std::size_t s = 2; // "{}"
  78.             for (std::size_t i = 0; i < vec.size(); i++) {
  79.                 s += fmt[i].estimate_size();
  80.                 if (i != vec.size() - 1) {
  81.                     s += 2; // ", "
  82.                 }
  83.             }
  84.             return s;
  85.         }
  86.  
  87.         void append_to(std::string& s) const {
  88.             s += "{";
  89.             for (std::size_t i = 0; i < vec.size(); i++) {
  90.                 fmt[i].append_to(s);
  91.                 if (i != vec.size() - 1) {
  92.                     s += ", ";
  93.                 }
  94.             }
  95.             s += "}";
  96.         }
  97.  
  98.     private:
  99.         const std::vector<T>& vec;
  100.         std::vector<FormatHelper<T>> fmt;
  101.     };
  102.  
  103.     template<typename T>
  104.     struct FormatHelper<T, std::enable_if_t<std::is_integral_v<T>>> {
  105.         constexpr static int BASE = 10;
  106.         // +1 for potential '-' and +1 because digits10 will be rounded down
  107.         constexpr static size_t BUF_SIZE = 2 + std::numeric_limits<T>::digits10;
  108.  
  109.         explicit FormatHelper(const T& val) : val(val) {}
  110.  
  111.         std::size_t estimate_size() const {
  112.             return BUF_SIZE;
  113.         }
  114.  
  115.         void append_to(std::string& s) const {
  116.             char buf[BUF_SIZE];
  117.             auto [end, ec] = std::to_chars(std::begin(buf), std::end(buf), val, BASE);
  118.             assert(ec == std::errc());
  119.             s += std::string_view(buf, end - buf);
  120.         }
  121.  
  122.     private:
  123.         const T& val;
  124.     };
  125.  
  126.     template<typename T>
  127.     struct FormatHelper<T, std::enable_if_t<validator::has_format_v<T>>> {
  128.         constexpr static std::size_t DEFAULT_SIZE = 10;
  129.  
  130.         explicit FormatHelper(const T& val) : val(val) {}
  131.  
  132.         std::size_t estimate_size() const {
  133.             return DEFAULT_SIZE;
  134.         }
  135.  
  136.         void append_to(std::string& s) const {
  137.             s += val.format();
  138.         }
  139.  
  140.     private:
  141.         const T& val;
  142.     };
  143.  
  144.     template<typename T>
  145.     std::enable_if_t<validator::has_format_helper_v<T>, std::string> make_string(const T& value) {
  146.         FormatHelper<T> helper(value);  // Explicit!
  147.         std::string formatted;
  148.         formatted.reserve(helper.estimate_size());
  149.         helper.append_to(formatted);
  150.         formatted.shrink_to_fit();
  151.         return formatted;
  152.     }
  153. }  // namespace format
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement