我相信使用完美转发和可变参数模板参数是可能的。
加入Str.hpp:
class joinStr {
public:
template<typename... Args>
joinStr(const std::string& first, Args&&... args): ret(""), size(0) {
size = first.length();
getSize((args)...);
std::cout << "before reserve : " << ret.capacity() << std::endl;
ret.reserve(size);
std::cout << "after reserve : " << ret.capacity() << std::endl;
ret.append(first);
join(std::forward<Args>(args)...);
}
~joinStr() {}
std::string getStr() {
std::cout << ret << std::endl;
return ret;
}
private:
std::string ret;
int size;
int getSize() {
std::cout << "size : " << size << std::endl;
return size;
}
template<typename... Args>
int getSize(const std::string& first, const Args&... args) {
size += first.length();
return getSize((args)...);
}
template<typename... Args>
int getSize(char* first, const Args&... args) {
size += strlen(first);
return getSize((args)...);
}
template<typename... Args>
int getSize(const char* first, const Args&... args) {
size += strlen(first);
return getSize((args)...);
}
void join() {
std::cout << "Final capacity : " << ret.capacity() << std::endl;
}
template<typename... Args>
void join(const std::string& first, Args&&... args) {
ret.append(first);
join(std::forward<Args>(args)...);
}
template<typename... Args>
void join(char* first, Args&&... args) {
ret.append(first);
join(std::forward<Args>(args)...);
}
template<typename... Args>
void join(const char* first, Args&&... args) {
ret.append(first);
join(std::forward<Args>(args)...);
}
};
主要:
int main() {
std::string s1 = "hello";
std::string s2 = "world !";
std::string s3 = "meatpopsicle";
const char* s4 = "__yeah__";
joinStr c(s1, s2, s3, s4);
return 1;
}
请注意,我将它包装在一个类中,但您可以在一个类之外执行相同的操作。
作为奖励,它同时适用于 std::string、const char* 和 char*。
编辑:修复了在 getSize 中重复使用移动的值并在 Caleth's 建议之后为 const char* 添加了模板
编辑 2 :
允许在 const char* 之后传递 size_t 字段而不是使用 strlen 的版本。
class joinStr {
public:
template<typename... Args>
joinStr(const std::string& first, Args&&... args): ret(""), size(0) {
size = first.length();
getSize(args...);
std::cout << "before reserve : " << ret.capacity() << std::endl;
ret.reserve(size);
std::cout << "after reserve : " << ret.capacity() << std::endl;
ret.append(first);
join(std::forward<Args>(args)...);
}
~joinStr() {}
std::string getStr() {
std::cout << ret << std::endl;
return ret;
}
private:
std::string ret;
int size;
int getSize() {
std::cout << "size : " << size << std::endl;
return size;
}
template<typename... Args>
int getSize(const std::string& first, const Args&... args) {
size += first.length();
return getSize((args)...);
}
// const char *
template<typename... Args, typename T>
int getSize(const char* first, const T& t, const Args&... args) {
getSizeImpl<T>(first, t, std::integral_constant<bool, std::is_same<T, size_t>::value>());
return getSize(t, args...);
}
template<typename T>
void getSizeImpl(const char* first, const T& t, std::false_type) {
// Case when the next argument is not a size_t type
size += strlen(first);
}
template<typename T>
void getSizeImpl(const char* first,const T& t, std::true_type) {
// Do nothing
}
template<typename... Args>
int getSize(size_t s, const Args&... args) {
size += s;
std::cout << "size_t " << s << " in getSize" << std::endl;
return getSize(args...);
}
void join() {
std::cout << "Final capacity : " << ret.capacity() << std::endl;
}
template<typename... Args>
void join(const std::string& first, Args&&... args) {
ret.append(first);
join(std::forward<Args>(args)...);
}
template<typename... Args>
void join(char* first, Args&&... args) {
ret.append(first);
join(std::forward<Args>(args)...);
}
template<typename... Args>
void join(const char* first, Args&&... args) {
ret.append(first);
join(std::forward<Args>(args)...);
}
template<typename... Args>
void join(size_t s, Args&&... args) {
join(std::forward<Args>(args)...);
}
};
主要:
int main() {
std::string s1 = "hello";
std::string s2 = "world !";
std::string s3 = "meatpopsicle";
const char* s4 = "__yeah__";
joinStr c(s1, s2, s3, s4, (size_t)8);
return 1;
}