0

I want to save different types of data in the class ContentField, so it has a private internal class Row which uses a template typename, so that it can save different types of data. So now in the Constructor of ContentField a parameter pack of a typename is asked for, so that values of different types can be passed as paramters. But when I call that Constructor in the main function I get a link error, but I can call the constructor if I remove the parameter pack. How can I fix this?

Edit: I can´t add #include "contentField.cpp" to the end of the header file, as proposed in the related question, as then I get a bunch of function has already been defined error and I also can´t use explicit instantiations because the class that is unresolved isn´t a template class but rather the private class Row inside of it and I want to use parameter packs, so I can´t do an explicit instantiations of every possible combination.

Error:

>main.obj : error LNK2019: unresolved external symbol "public: __cdecl ContentField::ContentField<int,int>(int,int)" (??$?0HH@ContentField@@QEAA@HH@Z) referenced in function main
1>F:\UniversalHelperBackend\x64\Debug\UniversalHelperBackend.exe : fatal error LNK1120: 1 unresolved externals

contentField.h:

#pragma once
#define VALID_TYPES 2
#include <string>
#include <list>
#include <memory>

using std::string;

class ContentField {
public:
    // Constructors
    template <typename... T> ContentField(T... values);
    //(int numberOfRows);
    //ContentField();

    // Functions
    void addRow();
    template <typename T> void addRow(T value);

private:
    // Internal Classes
    class RowBase {
    public:
        virtual ~RowBase() {}
    };

    template <typename T> class Row : RowBase {
    public:
        // Constructors
        Row(T value);

        string test();

    private:
        // Functions
        bool isValidType(T value);

        // Variables
        const type_info* validTypes[VALID_TYPES] = { &typeid(int), &typeid(string) };
        T value;
    };

    // Functions
    template <typename... T> void createRows(T... values);
    template <typename T> void createRow(T value);

    // Variables
    std::list<std::unique_ptr<RowBase>> rows;
};

contentField.cpp:

#include <stdexcept>
#include <iostream>
#include <string>
#include "contentField.h"

using std::string;

//
// ContentField
//
template <typename... T>
ContentField::ContentField(T... values) {
    createRows(std::forward<T>(values)...);
}

template <typename... T>
void ContentField::createRows(T... values) {
    (createRow(std::forward<T>(values)), ...);
}

template <typename T>
void ContentField::createRow(T value) {
    Row<T> newRow(value);
    newRow.test();
    rows.push_back(std::make_unique<Row<T>>(newRow));
}

//
// Row
//
template <typename T>
string ContentField::Row<T>::test() {
    std::cout << "TEST " + std::string(typeid(value).name()) >> std::endl;
}

main.h:

#pragma once
#include "contentField.h"

main.cpp:

#include <string>
#include <vector>
#include "main.h"

int main() {
    ContentField field(2, 1);

    return 0;
}
Bugsia
  • 25
  • 6
  • 3
    Side note: When you need a build diagnostic like a compiler or linker error from Visual Studio to go into a document like a Stackoverflow post, get it from the full text output in the Output tab usually located immediately next to the Error List tab. The Error List shows an executive summary formatted for graphical display. The Output tab shows the raw, complete, and unadulterated tool output formatted to be read as text. The Output generally looks better in text and, because it hasn't been summarized, often contains details omitted in the Error List that helps you solve the problem. – user4581301 Jun 15 '23 at 17:39

0 Answers0