string builder: Fix ambiguity issues
This commit is contained in:
parent
5eec3c3c9b
commit
5c004015ce
|
@ -12,47 +12,59 @@ namespace ConversionUtilities
|
|||
/// \cond
|
||||
namespace Helper {
|
||||
|
||||
template<class StringType, Traits::DisableIf<std::is_integral<StringType> > >
|
||||
template<class StringType, Traits::EnableIf<std::is_class<StringType> >...>
|
||||
std::size_t computeTupleElementSize(const StringType *str)
|
||||
{
|
||||
return str->size();
|
||||
}
|
||||
|
||||
template<class StringType>
|
||||
template<class StringType, Traits::EnableIf<std::is_class<StringType> >...>
|
||||
std::size_t computeTupleElementSize(const StringType &str)
|
||||
{
|
||||
return str.size();
|
||||
}
|
||||
|
||||
template<class CharType>
|
||||
template<class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType> >...>
|
||||
std::size_t computeTupleElementSize(const CharType *str)
|
||||
{
|
||||
return std::char_traits<CharType>::length(str);
|
||||
}
|
||||
|
||||
template<class StringType>
|
||||
template<class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType> >...>
|
||||
constexpr std::size_t computeTupleElementSize(CharType)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class StringType, Traits::EnableIf<std::is_class<StringType> >...>
|
||||
void append(StringType &target, const StringType *str)
|
||||
{
|
||||
target.append(*str);
|
||||
}
|
||||
|
||||
template<class StringType>
|
||||
template<class StringType, Traits::EnableIf<std::is_class<StringType> >...>
|
||||
void append(StringType &target, const StringType &str)
|
||||
{
|
||||
target.append(str);
|
||||
}
|
||||
|
||||
template<class StringType, class CharType>
|
||||
template<class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType> >...>
|
||||
void append(StringType &target, const CharType *str)
|
||||
{
|
||||
target.append(str);
|
||||
}
|
||||
|
||||
template<class StringType, class CharType, Traits::EnableIf<std::is_same<typename StringType::value_type, CharType> >...>
|
||||
void append(StringType &target, CharType c)
|
||||
{
|
||||
target += c;
|
||||
}
|
||||
|
||||
template<class StringType, class Tuple, std::size_t N>
|
||||
struct TupleToString {
|
||||
static std::size_t precomputeSize(const Tuple &tuple)
|
||||
{
|
||||
return TupleToString<StringType, Tuple, N-1>::precomputeSize(tuple) + computeTupleElementSize(std::get<N-1>(tuple));
|
||||
return TupleToString<StringType, Tuple, N-1>::precomputeSize(tuple) + computeTupleElementSize<StringType>(std::get<N-1>(tuple));
|
||||
}
|
||||
|
||||
static void append(const Tuple &tuple, StringType &str)
|
||||
|
@ -66,7 +78,7 @@ template<class StringType, class Tuple>
|
|||
struct TupleToString<StringType, Tuple, 1> {
|
||||
static std::size_t precomputeSize(const Tuple &tuple)
|
||||
{
|
||||
return computeTupleElementSize(std::get<0>(tuple));
|
||||
return computeTupleElementSize<StringType>(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<class Tuple>
|
||||
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<class Tuple>
|
||||
template<class Tuple, Traits::DisableIfAny<std::is_same<Tuple, std::string>, std::is_same<Tuple, const char *>, std::is_array<Tuple>, std::is_same<Tuple, char> >...>
|
||||
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<class Tuple>
|
||||
template<class Tuple, Traits::DisableIfAny<std::is_trivial<Tuple>, std::is_same<Tuple, std::string>, std::is_same<Tuple, const char *>, std::is_array<Tuple>, std::is_same<Tuple, char> >...>
|
||||
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<class Tuple, Traits::DisableIfAny<std::is_trivial<Tuple>, std::is_same<Tuple, std::string>, std::is_same<Tuple, const char *>, std::is_array<Tuple>, std::is_same<Tuple, char> >...>
|
||||
inline std::string operator +(const Tuple &lhs, char rhs)
|
||||
{
|
||||
return tupleToString(std::tuple_cat(lhs, std::make_tuple(rhs)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // CONVERSION_UTILITIES_STRINGBUILDER_H
|
||||
|
|
|
@ -306,10 +306,14 @@ string functionTakingString(const string &str)
|
|||
|
||||
void ConversionTests::testStringBuilder()
|
||||
{
|
||||
// conversion of string-tuple to string (the actual string builder)
|
||||
const tuple<const char *, string, const char *> 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");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue