diff --git a/conversion/stringbuilder.h b/conversion/stringbuilder.h index c7af011..69c9ea8 100644 --- a/conversion/stringbuilder.h +++ b/conversion/stringbuilder.h @@ -12,47 +12,59 @@ namespace ConversionUtilities /// \cond namespace Helper { -template > > +template >...> std::size_t computeTupleElementSize(const StringType *str) { return str->size(); } -template +template >...> std::size_t computeTupleElementSize(const StringType &str) { return str.size(); } -template +template >...> std::size_t computeTupleElementSize(const CharType *str) { return std::char_traits::length(str); } -template +template >...> +constexpr std::size_t computeTupleElementSize(CharType) +{ + return 1; +} + +template >...> void append(StringType &target, const StringType *str) { target.append(*str); } -template +template >...> void append(StringType &target, const StringType &str) { target.append(str); } -template +template >...> void append(StringType &target, const CharType *str) { target.append(str); } +template >...> +void append(StringType &target, CharType c) +{ + target += c; +} + template struct TupleToString { static std::size_t precomputeSize(const Tuple &tuple) { - return TupleToString::precomputeSize(tuple) + computeTupleElementSize(std::get(tuple)); + return TupleToString::precomputeSize(tuple) + computeTupleElementSize(std::get(tuple)); } static void append(const Tuple &tuple, StringType &str) @@ -66,7 +78,7 @@ template struct TupleToString { static std::size_t precomputeSize(const Tuple &tuple) { - return computeTupleElementSize(std::get<0>(tuple)); + return computeTupleElementSize(std::get<0>(tuple)); } static void append(const Tuple &tuple, StringType &str) @@ -125,6 +137,15 @@ constexpr auto operator %(const Tuple &lhs, const char *rhs) -> decltype(std::tu return std::tuple_cat(lhs, std::make_tuple(rhs)); } +/*! + * \brief Allows construction of string-tuples via %-operator, eg. string1 % "string2" % string3. + */ +template +constexpr auto operator %(const Tuple &lhs, char rhs) -> decltype(std::tuple_cat(lhs, std::make_tuple(rhs))) +{ + return std::tuple_cat(lhs, std::make_tuple(rhs)); +} + /*! * \brief Allows construction of string-tuples via %-operator, eg. string1 % "string2" % string3. */ @@ -149,6 +170,22 @@ constexpr auto operator %(const std::string &lhs, const char *rhs) -> decltype(s return std::make_tuple(&lhs, rhs); } +/*! + * \brief Allows construction of string-tuples via %-operator, eg. string1 % "string2" % string3. + */ +constexpr auto operator %(const std::string &lhs, char rhs) -> decltype(std::make_tuple(&lhs, rhs)) +{ + return std::make_tuple(&lhs, rhs); +} + +/*! + * \brief Allows construction of string-tuples via %-operator, eg. string1 % "string2" % string3. + */ +constexpr auto operator %(char lhs, const std::string &rhs) -> decltype(std::make_tuple(lhs, &rhs)) +{ + return std::make_tuple(lhs, &rhs); +} + /*! * \brief Allows construction of final string from previously constructed string-tuple and trailing string via +-operator. * @@ -158,7 +195,7 @@ constexpr auto operator %(const std::string &lhs, const char *rhs) -> decltype(s * printVelocity("velocity: " % numberToString(velocityExample) % " km/h (" % numberToString(velocityExample / 3.6) + " m/s)")); * ``` */ -template +template, std::is_same, std::is_array, std::is_same >...> inline std::string operator +(const Tuple &lhs, const std::string &rhs) { return tupleToString(std::tuple_cat(lhs, std::make_tuple(&rhs))); @@ -173,12 +210,27 @@ inline std::string operator +(const Tuple &lhs, const std::string &rhs) * printVelocity("velocity: " % numberToString(velocityExample) % " km/h (" % numberToString(velocityExample / 3.6) + " m/s)")); * ``` */ -template +template, std::is_same, std::is_same, std::is_array, std::is_same >...> inline std::string operator +(const Tuple &lhs, const char *rhs) { return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs))); } +/*! + * \brief Allows construction of final string from previously constructed string-tuple and trailing char via +-operator. + * + * This is meant to be used for fast string building without multiple heap allocation, eg. + * + * ``` + * printVelocity("velocity: " % numberToString(velocityExample) % " km/h (" % numberToString(velocityExample / 3.6) + " m/s)")); + * ``` + */ +template, std::is_same, std::is_same, std::is_array, std::is_same >...> +inline std::string operator +(const Tuple &lhs, char rhs) +{ + return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs))); +} + } #endif // CONVERSION_UTILITIES_STRINGBUILDER_H diff --git a/tests/conversiontests.cpp b/tests/conversiontests.cpp index d77ffd3..b81e47e 100644 --- a/tests/conversiontests.cpp +++ b/tests/conversiontests.cpp @@ -306,10 +306,14 @@ string functionTakingString(const string &str) void ConversionTests::testStringBuilder() { + // conversion of string-tuple to string (the actual string builder) const tuple tuple("string1", "string2", "string3"); CPPUNIT_ASSERT_EQUAL(string("string1string2string3"), tupleToString(tuple)); CPPUNIT_ASSERT_EQUAL(string("foobarfoo2bar2"), tupleToString(string("foo") % "bar" % string("foo2") % "bar2")); - CPPUNIT_ASSERT_EQUAL(string("123456"), functionTakingString("12" % string("34") + "56")); + + // construction of string-tuple and final conversion to string works + CPPUNIT_ASSERT_EQUAL_MESSAGE("result can be passed to any function taking a std::string", string("1234567"), functionTakingString("12" % string("34") % '5' + "67")); constexpr double velocityExample = 27.0; - CPPUNIT_ASSERT_EQUAL(string("velocity: 27 km/h (7.5 m/s)"), functionTakingString("velocity: " % numberToString(velocityExample) % " km/h (" % numberToString(velocityExample / 3.6) + " m/s)")); + CPPUNIT_ASSERT_EQUAL_MESSAGE("real-word example", string("velocity: 27 km/h (7.5 m/s)"), functionTakingString("velocity: " % numberToString(velocityExample) % " km/h (" % numberToString(velocityExample / 3.6) + " m/s)")); + CPPUNIT_ASSERT_EQUAL_MESSAGE("regular + operator still works (no problems with ambiguity)", string("regular + still works"), string("regular") + " + still works"); }