From 1fd208995b70f943edc324e7f89ca57a402fa85a Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Thu, 5 Dec 2019 14:58:37 +0100 Subject: Improve syntax and name of compile time variant --- cxxformat.hpp | 62 +++++++++++++++++++++++++++++++++++++++-------------------- main.cpp | 9 +++++---- 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/cxxformat.hpp b/cxxformat.hpp index 6a86e4c..1dd919e 100644 --- a/cxxformat.hpp +++ b/cxxformat.hpp @@ -411,34 +411,51 @@ private: template constexpr str appendCharHelper(const char c, std::index_sequence) const { - return str{s[indices]..., c, '\0'}; + return str{s[indices]..., c}; } template static constexpr str prependCharHelper(const char c, const str &s, std::index_sequence) { - return str{c, s.s[indices]..., '\0'}; + return str{c, s.s[indices]...}; } template constexpr str appendStrHelper(std::index_sequence, std::index_sequence) const { - return str{s[ownIndices]..., other.s[othersIndices]..., '\0'}; + return str{s[ownIndices]..., other.s[othersIndices]...}; } + public: + template + constexpr str(const char (&s)[N + 1], std::index_sequence) : s{s[indices]...} + { + + } + + constexpr str(const char (&s)[N + 1]) : str{s, std::make_index_sequence()} + { + + } + + template + constexpr str(Chars... chars) : s{chars..., '\0'} + { + static_assert(N == sizeof...(chars), "O.o"); + } template - constexpr char get(str_index) const + constexpr char get() const { static_assert(index < N, "str::get: index out of range"); return s[index]; } template - constexpr str extract(std::index_sequence, str_index = str_index<0>{}) const + constexpr str extract(std::index_sequence) const { static_assert(((indices + offset < N) && ...), "str::extract: index out of range"); - return str{s[indices + offset]..., '\0'}; + return str{s[indices + offset]...}; } constexpr str operator+(const char c) const @@ -465,28 +482,31 @@ constexpr str operator+(const char c, const str &other) template str(const char(&)[N]) -> str; +template +str(Chars... chars) -> str; + namespace detail { template constexpr char get(const str& s) { - return s.get(str_index{}); + return s.template get(); } template constexpr str extractStr(const str &source, std::index_sequence) { - return str{get(source)..., '\0'}; + return str{get(source)...}; } template constexpr str substr(const str &s) { - static_assert(!endIsIndex || end < N, "End index / substr-length is out of range"); - if constexpr (end == std::string::npos) return substr(s); + static_assert(!endIsIndex || end < N, "substr: end index / substr-length is out of range"); + if constexpr (!endIsIndex && end == 0) return str<0>{}; + else if constexpr (end == std::string::npos) return substr(s); else if constexpr (!endIsIndex) return substr(s); - else if constexpr (endIsIndex && end + 1 - start == 0) return str{""}; - else return s.extract(std::make_index_sequence(), str_index{}); + else return s.template extract(std::make_index_sequence()); } template @@ -532,7 +552,7 @@ namespace detail return str<1>{'0' + N}; } else return toStr() + char(N % 10 + '0'); - }; + } template std::string format_s() @@ -608,15 +628,15 @@ namespace detail constexpr char conversion = checkReplaceAutoConversion(fmt), argumentIndex>(std::forward(arg)); - if constexpr (conversion == 'c') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "character", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); - else if constexpr (conversion == 'd' || conversion == 'i') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "signed integer", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); - else if constexpr (conversion == 'u' || conversion == 'o' || conversion == 'x' || conversion == 'X') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "unsigned integer", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); - else if constexpr (conversion == 'e' || conversion == 'E' || conversion == 'f' || conversion == 'F' || conversion == 'g' || conversion == 'G' || conversion == 'a' || conversion == 'A') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "double", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); - else if constexpr (conversion == 'p') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "pointer", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); + if constexpr (conversion == 'c') return substr<0, i>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "character", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); + else if constexpr (conversion == 'd' || conversion == 'i') return substr<0, i>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "signed integer", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); + else if constexpr (conversion == 'u' || conversion == 'o' || conversion == 'x' || conversion == 'X') return substr<0, i>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "unsigned integer", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); + else if constexpr (conversion == 'e' || conversion == 'E' || conversion == 'f' || conversion == 'F' || conversion == 'g' || conversion == 'G' || conversion == 'a' || conversion == 'A') return substr<0, i>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "double", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); + else if constexpr (conversion == 'p') return substr<0, i>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "pointer", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); else if constexpr (conversion == 's') { const auto& string = convert>, false>(std::forward(arg), "string", argumentIndex); - return substr<0, i - 1, true>(fmt).s + strprintf((str{"%."}.s + std::to_string(determineStringPrecision(string)) + 's').c_str(), string.data()) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); + return substr<0, i>(fmt).s + strprintf((str{"%."}.s + std::to_string(determineStringPrecision(string)) + 's').c_str(), string.data()) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); } else { @@ -628,8 +648,8 @@ namespace detail } } -template -std::string format_s(Args &&...args) +template +std::string format(Args &&...args) { return detail::format_s(std::forward(args)...); } diff --git a/main.cpp b/main.cpp index bea2436..62c55de 100644 --- a/main.cpp +++ b/main.cpp @@ -40,11 +40,12 @@ struct format::AutoConversion> : format::SimpleAutoConversion<' template struct format::AutoConversion, char>>> : format::SimpleAutoConversion<'s', const T(&)[N]> {}; -int main(int argc, char *argv[]) +int main(int, char *[]) { - const std::array array[] = {std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}}; - std::cout << format::format_s("World", 7, 3.5, &array) << std::endl; - std::cout << format::format("%v%v%v%v%v", 'H', 'e', 'l', 'l', 'o') << std::endl; + constexpr std::array array[] = {std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}}; + + std::cout << format::format<"Hello %s: %d %03.5f %V">("World", 7, 3.5, array) << std::endl; + std::cout << format::format<"%v%v%v%v%v">('H', 'e', 'l', 'l', 'o') << std::endl; std::cout << format::format("%V", &array) << std::endl; std::cout << format::format("%s", std::array{1, 2, 3, 4, 5}) << std::endl; std::cout << format::format("Hello %v: %-7v %v", "World", 3.5, 5) << std::endl; -- cgit v1.2.3-54-g00ecf