Context
So I have a parser which can parse many different types of objects. I parse one file per object type using a function that has this typing:
template <typename T>
std::vector<T *> parseFeaturesfromFile(std::string)
And when creating an object World
, I use this function like this (in the constructor of World
):
const std::vector<C_type *> c_types = struct_parser.parseFeaturesfromFile<C_type>(file_path);
where c_types
is defined in the World
as
const std::vector<C_type *> c_types;
Error
The following error has cause me headaches for the last few days:
undefined reference to `std::vector<C_type*, std::allocator<C_type*> > parser::parseFeaturesfromFile<C_type>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
collect2.exe: error: ld returned 1 exit status
mingw32-make[1]: *** [Makefile.Debug:123: debug/Project.exe] Error 1
So what happens, if I understand this correctly, is that this function which adds values to my c_types
vector, has the extra type allocator<C_type*>
.
This could be because the problem actually lies with me using template functions incorrectly or something, however, many google searches later, I haven't found anywhere online where the allocator suddenly appeared where it shouldn't have.
This problem also appeared when trying to parse the other objects, for which you can freely replace all definition of C_type
with D_type
.
Another weird thing to note is that the compiler does not give any errors of bad typing in the parser.cpp
or parser.h
files. No warnings either.
The parseFeatures
itself has worked on one of the types before, and this should not be the issue. Also, a functional error in my code would not lead to an error like this, I think.
Context of functions giving the errors
Additional context of the functions will be provided here.
parser.cpp
template<typename T>
std::vector<T *> parser::parseFeaturesfromFile(std::string filepath)
{
loadfile(filepath);
std::vector<T *> features = parseFeatures<T>();
return features;
}
This function uses parseFeatures:
(The important part, imo, is where the elements are added to the vector via: features.push_back(feature);
)
template<typename T>
std::vector<T *> parser::parseFeatures()
{
// make empty list
std::vector<T *> features;
while (input) {
// get line content
std::string line;
getline(input, line);
// continue if line only has whitespace
if (std::regex_match(line, match_result, regex_whitespace_line)) {
continue;
}
// if feature header, append new feature
if (std::regex_match(line, match_result, regex_feature_header)) {
std::string base = match_result[1].str();
if (base == "Logistics" || base == "Production" || base == "Decoration" || base == "Vehicle" || base == "Cargo") {
T * feature = new T;
features.push_back(feature);
}
else {
throwParseError("Feature header");
}
}
// if attribute, apply it to the latest mentioned feature
if (std::regex_match(line, match_result, regex_attribute_andCo)) {
if (match_result.size() == 3) { // 2 groups matched
std::string base = match_result[1].str();
std::string rest = match_result[2].str();
// get value(s) for attribute
if (base == "name") {
std::regex_match(rest, match_result, regex_string);
features.back()->name = QString::fromStdString(match_result[1].str());
}
else if (base == "price") {
std::regex_match(rest, match_result, regex_int);
features.back()->price = std::stoi(match_result[1].str());
}
else {
throwParseError("Attribute");
}
}
}
// end of file
if (!input)
{
break;
}
}
return features;
}
Related hardware/software
I use QT Creator IDE, kit: Desktop Qt 6.0.2 MinGW 64-bit
.