diff options
-rw-r--r-- | libadhocutil/compileTimeFormatter.h | 50 | ||||
-rw-r--r-- | libadhocutil/unittests/Jamfile.jam | 15 | ||||
-rw-r--r-- | libadhocutil/unittests/testCompileTimeFormatter.cpp | 2 |
3 files changed, 65 insertions, 2 deletions
diff --git a/libadhocutil/compileTimeFormatter.h b/libadhocutil/compileTimeFormatter.h index 0a86946..c3837fe 100644 --- a/libadhocutil/compileTimeFormatter.h +++ b/libadhocutil/compileTimeFormatter.h @@ -6,10 +6,17 @@ #include <optional> #include <array> #include <boost/preprocessor/variadic/size.hpp> -#include "unique.h" namespace AdHoc { +#ifdef __cpp_nontype_template_parameter_class +#define USE_FIXED_STRING +#endif + +#ifdef USE_FIXED_STRING +#define CtfString const auto +#else #define CtfString const auto & +#endif // Template char utils template<typename char_type> constexpr bool isdigit(const char_type & ch) @@ -236,9 +243,45 @@ namespace AdHoc { #endif } +#ifdef USE_FIXED_STRING + // New C++20 implementation + namespace support { + template<typename CharT, std::size_t N> + class basic_fixed_string : public std::array<CharT, N> { + public: + constexpr basic_fixed_string(const CharT (&str)[N + 1]) + { + for (decltype(N) x = 0; x < N; x++) { + this->at(x) = str[x]; + } + } + constexpr basic_fixed_string(const CharT * str, decltype(N) len) + { + for (decltype(N) x = 0; x < len; x++) { + this->at(x) = str[x]; + } + } + }; + + template<typename CharT, std::size_t N> + basic_fixed_string(const CharT (&str)[N]) -> basic_fixed_string<CharT, N - 1>; + } + + template<const support::basic_fixed_string Str> + class LiteralFormatter : public FormatterDetail<Str, Str.size()> { }; + + template <const auto & S, decltype(strlen(S)) L = strlen(S)> + class Formatter : public FormatterDetail<support::basic_fixed_string< + typename std::decay<decltype(S[0])>::type, L>(S, L), L> { }; + +#define AdHocFormatter(name, str) \ + using name = LiteralFormatter<str> + +#else + // Classic pre-C++20 implementation +#include "unique.h" template <const auto & S, decltype(strlen<S>()) L = strlen<S>()> class Formatter : public FormatterDetail<S, L> { }; -} #define AdHocFormatterTypedef(name, str, id) \ inline constexpr auto id = str; \ @@ -247,4 +290,7 @@ namespace AdHoc { AdHocFormatterTypedef(name, str, MAKE_UNIQUE(name)) #endif +} + +#endif diff --git a/libadhocutil/unittests/Jamfile.jam b/libadhocutil/unittests/Jamfile.jam index d62f6da..e2b1f7c 100644 --- a/libadhocutil/unittests/Jamfile.jam +++ b/libadhocutil/unittests/Jamfile.jam @@ -39,6 +39,21 @@ run ; run + testCompileTimeFormatter.cpp + : : : + <define>ROOT=\"$(me)\" + <define>BOOST_TEST_DYN_LINK + <library>..//adhocutil + <library>stdc++fs + <library>boost_utf + -<cxxstd>17 + <cxxstd>2a + <implicit-dependency>lorem-ipsum + : + testCompileTimeFormatter20 + ; + +run testUriParse.cpp : : : <define>ROOT=\"$(me)\" diff --git a/libadhocutil/unittests/testCompileTimeFormatter.cpp b/libadhocutil/unittests/testCompileTimeFormatter.cpp index ba8a46f..369b804 100644 --- a/libadhocutil/unittests/testCompileTimeFormatter.cpp +++ b/libadhocutil/unittests/testCompileTimeFormatter.cpp @@ -77,6 +77,7 @@ namespace AdHoc { }; } +#ifndef __cpp_nontype_template_parameter_class // Compile string util assertions static_assert(strlen<formatEdgeCaseEmpty>() == 0); static_assert(strlen<formatEdgeCaseSingle>() == 1); @@ -113,6 +114,7 @@ static_assert(strchrnul<formatEdgeCaseFormatLonely, '%'>() == 0); static_assert(strchrnul<formatEdgeCaseFormatLonely, '?'>() == 1); static_assert(strchrnul<formatStringLiteral, 'e'>() == 3); static_assert(strchrnul<formatStringLiteral, 'f'>() == 7); +#endif BOOST_FIXTURE_TEST_SUITE( TestStreamWrite, std::stringstream ) |