summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libadhocutil/compileTimeFormatter.h50
-rw-r--r--libadhocutil/unittests/Jamfile.jam15
-rw-r--r--libadhocutil/unittests/testCompileTimeFormatter.cpp2
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 )