考虑这个简单的连接函数实现。
#include <iostream>
#include <string>
namespace detail {
template<typename... Args>
size_t calcSize(const Args&... args);
inline size_t calcSize(const std::string& head) {
return head.size();
}
template<size_t N>
size_t calcSize(char const(&) [N]) {
return N - 1;
}
template<typename... Tail>
size_t calcSize(const std::string& head, const Tail&... tail) {
return head.size() + calcSize(tail...);
}
template<size_t N, typename... Tail>
size_t calcSize(char const(&) [N], const Tail&... tail) {
return N - 1 + calcSize(tail...);
}
template<typename... Args>
void fillResult(std::string& result,
size_t startIndex,
const Args&... args);
inline void fillResult(std::string& result,
size_t startIndex,
const std::string& head) {
for (size_t i = 0; i < head.size(); ++i) {
if (head[i] == '\0') {
break;
}
result[startIndex++] = head[i];
}
}
template<size_t N>
void fillResult(std::string& result,
size_t startIndex,
char const(&head) [N]) {
for (size_t i = 0; i < N; ++i) {
if (head[i] == '\0') {
break;
}
result[startIndex++] = head[i];
}
}
template<typename... Tail>
void fillResult(std::string& result,
size_t startIndex,
const std::string& head,
const Tail&... tail) {
for (size_t i = 0; i < head.size(); ++i) {
if (head[i] == '\0') {
break;
}
result[startIndex++] = head[i];
}
fillResult(result, startIndex, tail...);
}
template<size_t N, typename... Tail>
void fillResult(std::string& result,
size_t startIndex,
char const(&head) [N],
const Tail&... tail) {
for (size_t i = 0; i < N; ++i) {
if (head[i] == '\0') {
break;
}
result[startIndex++] = head[i];
}
fillResult(result, startIndex, tail...);
}
}
template<typename... Args>
std::string join(const Args&... args) {
std::string result;
result.resize(detail::calcSize(args...));
detail::fillResult(result, 0, args...);
return result;
}
int main() {
std::cout << join("ab", "cd", "ef", "gh") << std::endl;
std::cout << join(std::string("ab"), std::string("cd"), std::string("ef")) << std::endl;
std::cout << join(std::string("ab"), "cd") << std::endl;
//std::cout << join(std::string("ab"), "cd", "ef") << std::endl;
//std::cout << join(std::string("ab"), "cd", std::string("ef")) << std::endl;
return 0;
}
它适用于main中的三个第一行,如果取消注释两个最后一次调用中的任何一个,则会因链接器错误而失败。尝试用gcc 4.9和clang得到相同的结果。任何人都可以指出什么是错的? 以下是coliru http://coliru.stacked-crooked.com/a/f55aa64fb4861e43
的链接答案 0 :(得分:1)
我认为这基本上是一个格式错误的程序,因为如果在使用时看到所有重载,你最终会使用不会被使用的重载。这是因为您想要的重载在实际需要时尚未实际声明。要解决此问题,只需预先添加所有声明:
namespace detail {
template<typename... Args>
size_t calcSize(const Args&... args);
template<size_t N, typename... Tail>
size_t calcSize(char const(&) [N], const Tail&... tail);
template<typename... Tail>
size_t calcSize(const std::string& head, const Tail&... tail);
template<typename... Tail>
void fillResult(std::string& result,
size_t startIndex,
const std::string& head,
const Tail&... tail);
template<size_t N, typename... Tail>
void fillResult(std::string& result,
size_t startIndex,
char const(&head) [N],
const Tail&... tail);