I have C++14 code like this.
I am updating to C++17. Is there a way this to be rewritten as fold expression?
namespace cat_impl_{
inline size_t catSize(std::string_view const first) {
return first.size();
}
template<typename... Args>
size_t catSize(std::string_view const first, Args &&... args) {
return catSize(first) + catSize(std::forward<Args>(args)...);
}
inline void cat(std::string &s, std::string_view const first) {
s.append(first.data(), first.size());
}
template<typename... Args>
void cat(std::string &s, std::string_view const first, Args &&... args) {
cat(s, first);
cat(s, std::forward<Args>(args)...);
}
}
template<typename... Args>
std::string concatenate(Args &&... args){
// super cheap concatenation,
// with single allocation
using namespace cat_impl_;
size_t const reserve_size = catSize(std::forward<Args>(args)...);
std::string s;
s.reserve(reserve_size);
cat(s, std::forward<Args>(args)...);
return s;
}
Yes
template <typename... Args>
std::size_t catSize (Args &&... args) {
return (... + std::forward<Args>(args).size());
}
and
template <typename... Args>
void cat (std::string &s, Args ... args) {
(s.append(args.data(), args.size()), ...);
}
or also (more generic, not only for std::string_view
)
template <typename ... Args>
void cat (std::string &s, Args && ... args) {
(s += std::forward<Args>(args), ...);
}
Or, maybe, you can avoid at all cat()
and catSize()
and simply write something as
template <typename... Args>
std::string concatenate (Args &&... args) {
std::string s;
s.reserve((args.size() + ...));
return (s += std::forward<Args>(args), ...);
}
Off Topic: avoid a double std::forward
, for the same object, in a function (see double std::forward
over your args
in your original concatenate()
).