Ensure no copy is made when using argsToString()
It seems that std::make_tuple() is using __decay_and_strip so the arguments get copied. Using the std::tuple c'tor directly instead. When using the %-operator it is already taken care that strings are stored as pointers and not by value.
This commit is contained in:
parent
c7c5352325
commit
8744cf95ef
|
@ -241,6 +241,11 @@ constexpr void append(StringType &target, TupleType &&tuple, typename StringType
|
|||
return TupleToString<StringType, TupleType, std::tuple_size_v<std::decay_t<TupleType>>>::append(std::forward<TupleType>(tuple), target);
|
||||
}
|
||||
|
||||
template <typename... Elements> constexpr std::tuple<Elements &&...> makeTupleHoldingRefsToTemporaryObjects(Elements &&... args) noexcept
|
||||
{
|
||||
return std::tuple<Elements &&...>(std::forward<Elements>(args)...);
|
||||
}
|
||||
|
||||
} // namespace Helper
|
||||
/// \endcond
|
||||
|
||||
|
@ -257,7 +262,7 @@ template <class StringType = std::string, class... Args> inline StringType tuple
|
|||
|
||||
template <class StringType = std::string, class... Args> inline StringType argsToString(Args &&... args)
|
||||
{
|
||||
return tupleToString(std::make_tuple(std::forward<Args>(args)...));
|
||||
return tupleToString(Helper::makeTupleHoldingRefsToTemporaryObjects(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -387,6 +387,23 @@ struct ConvertibleToString {
|
|||
operator std::string() const;
|
||||
};
|
||||
|
||||
struct StringThatDoesNotLikeToBeCopiedOrMoved : public std::string {
|
||||
explicit StringThatDoesNotLikeToBeCopiedOrMoved(const char *value)
|
||||
: std::string(value)
|
||||
{
|
||||
}
|
||||
[[noreturn]] StringThatDoesNotLikeToBeCopiedOrMoved(const StringThatDoesNotLikeToBeCopiedOrMoved &other)
|
||||
: std::string(other)
|
||||
{
|
||||
CPPUNIT_FAIL("attempt to copy string: " + other);
|
||||
}
|
||||
[[noreturn]] StringThatDoesNotLikeToBeCopiedOrMoved(StringThatDoesNotLikeToBeCopiedOrMoved &&other)
|
||||
: std::string(std::move(other))
|
||||
{
|
||||
CPPUNIT_FAIL("attempt to move string: " + other);
|
||||
}
|
||||
};
|
||||
|
||||
void ConversionTests::testStringBuilder()
|
||||
{
|
||||
// check whether type traits work as expected
|
||||
|
@ -398,7 +415,8 @@ void ConversionTests::testStringBuilder()
|
|||
static_assert(Helper::IsStringViewType<std::wstring, std::wstring_view>::value);
|
||||
static_assert(Helper::IsConvertibleToConstStringRef<std::string, ConvertibleToString>::value);
|
||||
#ifdef CPP_UTILITIES_USE_STANDARD_FILESYSTEM
|
||||
static_assert(!Helper::IsConvertibleToConstStringRef<std::filesystem::path::string_type, std::filesystem::path>::value, "conversion via native() preferred");
|
||||
static_assert(!Helper::IsConvertibleToConstStringRef<std::filesystem::path::string_type, std::filesystem::path>::value,
|
||||
"conversion via native() preferred");
|
||||
#endif
|
||||
static_assert(
|
||||
!Helper::IsConvertibleToConstStringRef<std::string, std::string>::value, "yes, in this context this should not be considered convertible");
|
||||
|
@ -428,4 +446,10 @@ void ConversionTests::testStringBuilder()
|
|||
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
||||
"regular + operator still works (no problems with ambiguity)"s, "regular + still works"s, "regular"s + " + still works");
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("using string_view", "foobar123"s, "foo"sv % "bar"sv + 123);
|
||||
|
||||
// check that for the internal tuple construction no copies are made
|
||||
StringThatDoesNotLikeToBeCopiedOrMoved str(" happen ");
|
||||
const StringThatDoesNotLikeToBeCopiedOrMoved str2("for this");
|
||||
CPPUNIT_ASSERT_EQUAL("no copy/move should happen for this!"s,
|
||||
argsToString(StringThatDoesNotLikeToBeCopiedOrMoved("no copy/move should"), str, str2, StringThatDoesNotLikeToBeCopiedOrMoved("!")));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue