Reputation: 21
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
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