I have come across a compiler error involving variadic templates. The following code is a strongly simplified version which reproduces the error in my original code:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
typedef std::vector<std::string> stringvec;
// dummy function: return string version of first vectorelemenr
template<typename T>
std::string vecDummy(const std::string sFormat, const T t) {
std::stringstream ss("");
if (t.size() > 0) {
ss << t[0];
}
return ss.str();
}
// recursion termination
std::string recursiveY(stringvec &vFlags, uint i) {
return "";
}
// walk through arguments
template<typename T, typename... Args>
std::string recursiveY(stringvec &vFlags, uint i, T value, Args... args) {
std::string sRes = "";
if (vFlags[i] == "%v") {
sRes += vecDummy(vFlags[i], value);
}
sRes += " "+recursiveY(vFlags, i+1, args...);
return sRes;
}
int main(void) {
stringvec vPasta = {"spagis", "nudle", "penne", "tortellini"};
stringvec vFormats = {"%v", "%s"};
std::string st = "";
st += recursiveY(vFormats, 0, vPasta, "test12");
std::cout << ">>" << st << "<<" << std::endl;
return 0;
}
This simple code should walk through the arguments passed to recursiveY()
and, if the current format string is "%v" it would pass the corresponding argument to vecDummy()
which would return a string version of the vector's first element (if there is one).
The error message from the compiler is
sptest2.cpp: In instantiation of ‘std::string vecDummy(std::string, T) [with T = const char*; std::string = std::__cxx11::basic_string<char>]’:
sptest2.cpp:30:25: required from ‘std::string recursiveY(stringvec&, uint, T, Args ...) [with T = const char*; Args = {}; std::string = std::__cxx11::basic_string<char>; stringvec = std::vector<std::__cxx11::basic_string<char> >; uint = unsigned int]’
sptest2.cpp:32:27: required from ‘std::string recursiveY(stringvec&, uint, T, Args ...) [with T = std::vector<std::__cxx11::basic_string<char> >; Args = {const char*}; std::string = std::__cxx11::basic_string<char>; stringvec = std::vector<std::__cxx11::basic_string<char> >; uint = unsigned int]’
sptest2.cpp:43:21: required from here
sptest2.cpp:12:11: error: request for member ‘size’ in ‘t’, which is of non-class type ‘const char* const’
12 | if (t.size() > 0) {
| ~~^~~~
It seems as if the compiler uses all types i pass to recursiveY()
in main, but vecDummy()
is designed to only work with vectors of some kind (and not with const char*
, for example).
Is there a possibility to modify this code so that it will work as intended?
Is there perhaps a way of assuring the compiler that i will only pass vectors to vecDummy()
(even at the risk of a runtime error or unexpected behaviour - similar to passing an integer to printf()
when it expects a string)?
You can add an overload of vecDummy
that handles the std::vector
case and 'dumb down' the more general one to (say) just return an empty string:
// dummy function: return string version of first vectorelement (catch-all)
template<typename T>
std::string vecDummy(const std::string, const T) {
return "";
}
// dummy function: return string version of first vectorelement (vectors only)
template<typename T>
std::string vecDummy(const std::string, const std::vector <T> &t) {
std::stringstream ss("");
if (t.size() > 0) {
ss << t[0];
}
return ss.str();
}