From 138b84c1efd1e3e7b82ff1d9a19b45a905d5a031 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 18 Jan 2019 15:41:31 +0000 Subject: Literal operator based inline formatting --- libadhocutil/compileTimeFormatter.h | 44 +++++++++++++++------- .../unittests/testCompileTimeFormatter.cpp | 14 +++++++ 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/libadhocutil/compileTimeFormatter.h b/libadhocutil/compileTimeFormatter.h index 5f0237e..6a932be 100644 --- a/libadhocutil/compileTimeFormatter.h +++ b/libadhocutil/compileTimeFormatter.h @@ -137,6 +137,11 @@ namespace AdHoc { std::basic_stringstream s; return write(s, pn...).str(); } + template + inline auto operator()(const Pn & ... pn) const + { + return get(pn...); + } /** * Write the result of formatting to the given stream. @@ -149,6 +154,11 @@ namespace AdHoc { { return Parser::run(s, pn...); } + template + inline stream & operator()(stream & s, const Pn & ... pn) const + { + return write(s, pn...); + } private: template @@ -179,23 +189,31 @@ namespace AdHoc { } }; }; + + namespace literals { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template" +#endif + template struct FMT + { + static constexpr char __FMT[] = {t...}; + }; + template inline auto operator""_fmt() noexcept + { + return AdHoc::Formatter::__FMT, sizeof...(t)>(); + } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } } #define AdHocFormatterTypedef(name, str, id) \ - inline constexpr auto id = str; \ - typedef ::AdHoc::Formatter name + inline constexpr auto id = str; \ + typedef ::AdHoc::Formatter name #define AdHocFormatter(name, str) \ - AdHocFormatterTypedef(name, str, MAKE_UNIQUE(name)) - -// As far as I know, only clang/llvm version 5+ can compile this -// so long as std=c++17 -#if __clang_major__ >= 5 && __cplusplus >= 201703 -#define scprintf(strmp, fmt, ...) \ - ([](decltype(strmp) & strm) -> auto & { \ - static constexpr auto __FMT = fmt; \ - return ::AdHoc::Formatter<__FMT>::write(strm, ##__VA_ARGS__); \ - }(strmp)) -#endif + AdHocFormatterTypedef(name, str, MAKE_UNIQUE(name)) #endif diff --git a/libadhocutil/unittests/testCompileTimeFormatter.cpp b/libadhocutil/unittests/testCompileTimeFormatter.cpp index 37d1947..65fbaa0 100644 --- a/libadhocutil/unittests/testCompileTimeFormatter.cpp +++ b/libadhocutil/unittests/testCompileTimeFormatter.cpp @@ -458,3 +458,17 @@ BOOST_AUTO_TEST_CASE(scprintf) } #endif +using namespace AdHoc::literals; + +BOOST_AUTO_TEST_CASE(user_defined_literal_fmt_get) +{ + BOOST_CHECK_EQUAL("foo 42", "foo %?"_fmt(42)); +} + +BOOST_AUTO_TEST_CASE(user_defined_literal_fmt_write) +{ + std::stringstream str; + "foo %?"_fmt(str, 42); + BOOST_CHECK_EQUAL("foo 42", str.str()); +} + -- cgit v1.2.3