Рассмотрите эту простую реализацию функции соединения.Шаблон функции странная ошибка компоновщика
#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;
}
Он отлично подходит для трех первых линий в главном и не работает с ошибкой компоновщика, если вы раскомментируете любое из двух последних вызовов. Пробовал gcc 4.9 и стучал с тем же результатом. Может ли кто-нибудь указать, что случилось? Вот ссылка на coliru http://coliru.stacked-crooked.com/a/f55aa64fb4861e43
[Demo] (http://coliru.stacked-crooked.com/a/db7d6473fedd0cb5) –
Спасибо, он работает сейчас. Но я до сих пор не понимаю, почему это ошибка ** линкер ** вместо ошибки компиляции. – user6256186
@ user6256186: Он плохо сформирован, никакой диагностики не требуется. Ваша программа выбирает первый шаблон функции 'template size_t calcSize (const Args & ... args)' в рекурсивном вызове, а не предполагаемая перегрузка, и (выбранная специализация) этот шаблон не определен. –