user3612348
user3612348

Reputation: 21

error LNK2019: unresolved external symbol

I need your help. I have no idea what is wrong with the code. "Feature" is a template base class with pure virtual function and "AvgSentenceLength" is a child class, but it seems that the problem appears while calling "oneValueMap" function of the base class. The error is:

1>avgSentenceLength.obj : error LNK2019: unresolved external symbol "protected: class std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,double,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,double> > > __thiscall Feature<class Text>::oneValueMap(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,double)" (?oneValueMap@?$Feature@VText@@@@IAE?AV?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@NU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@N@std@@@2@@std@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@N@Z) в функции "public: virtual class std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,double,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,double> > > __thiscall AvgSentenceLength::calculate(class Text)" (?calculate@AvgSentenceLength@@UAE?AV?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@NU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@N@std@@@2@@std@@VText@@@Z)

feature.h

#ifndef FEATURE_H   
#define FEATURE_H

#include <string>
#include <map>

using namespace std;

template <class T> class Feature
{
public:
    virtual map<string, double> calculate(T input) = 0;
protected:
    map<string, double> oneValueMap(string name, double value);
};

#endif FEATURE_H

feature.cpp

#include "feature.h"

template <class T> map<string, double> Feature<T>::oneValueMap(string name, double value)
{
    map<string, double> oneValueMap;

    oneValueMap.insert(pair<string, double>(name, value));

    return oneValueMap;
}

avgSentenceLength.h

#include "text.h"
#include "feature.h"

class AvgSentenceLength : public Feature<Text>
{
public:
    map<string, double> calculate(Text text);
};

avgSentenceLength.cpp

#include "avgSentenceLength.h"

map<string, double> AvgSentenceLength::calculate(Text text)
{
    double sum = 0.0;
    string name = "AvgSentenceLength";

    for (Sentence sentence: text.getText()) {
        for (Token word: sentence.getText()) {
            if (word.getType() == TokenType::tokenType::WORD) {
                sum = sum + 1;
            }
        }
    }

    return oneValueMap(name, sum / text.getLength()); //getLength() returns int
}

Upvotes: 0

Views: 6106

Answers (1)

rodrigo
rodrigo

Reputation: 98526

The problem is that your specialization of Feature<Text>::opeValueMap() is not defined.

That is because the specialization is in avgSentenceLength.cpp but the definition is in feature.cpp. The are separated compilation units, so the definition cannot be used for the specialization.

Generally speaking you should put all your template code, event the function definitions, in the .h file.

An alternative, if you know all the specializations that will be needed, is to add explicit instantiations of the code to feature.cpp and let the linker to its job:

template <class T> map<string, double> Feature<T>::oneValueMap(string name, double value)
{
    map<string, double> oneValueMap;

    oneValueMap.insert(pair<string, double>(name, value));

    return oneValueMap;
}

//explicit instantiations
template map<string, double> Feature<Text>::oneValueMap(string name, double value);
template map<string, double> Feature<Foo>::oneValueMap(string name, double value);
template map<string, double> Feature<Bar>::oneValueMap(string name, double value);

Upvotes: 3

Related Questions