Betrachten Sie diese einfache Join-Funktion Implementierung.Vorlage Funktionen seltsam Linker Fehler
#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;
}
Es funktioniert gut für die drei ersten Zeilen in Main und schlägt mit Linker-Fehler, wenn Sie einen der letzten zwei Aufrufe auskommentieren. Versucht mit gcc 4.9 und clang mit dem gleichen Ergebnis. Kann jemand darauf hinweisen, was falsch ist? Hier ist ein Link http://coliru.stacked-crooked.com/a/f55aa64fb4861e43
[Demo] (http://coliru.stacked-crooked.com/a/db7d6473fedd0cb5) –
Danke, es funktioniert jetzt. Aber ich verstehe immer noch nicht, warum es ein ** Linker ** Fehler statt eines Kompilierungsfehlers ist. – user6256186
@ user6256186: Es ist schlecht geformt, keine Diagnose erforderlich. Ihr Programm wählt die erste Funktionsvorlage 'template size_t calcSize (constArgs & ... args)' im rekursiven Aufruf aus, nicht die beabsichtigte Überladung und (die gewählte Spezialisierung von) diese Vorlage ist nicht definiert. –