As the title states, I am getting the infamous unresolved external symbol
linker issue.
I have already moved everything in the .h
files. The template classes are no longer split between .h
and .cpp
files.
I have included them in the main file. I have triple-quadruple checked that the definition is there (obviously).
My files are as follows:
Utils.h
:
Just a pretty cout for vector
and valarray
. Tested and working.
#pragma once
#include <vector>
#include <valarray>
#include <ostream>
using std::vector;
using std::valarray;
using std::ostream;
template <typename ValueType>
ostream& operator<< (ostream&, vector<ValueType>);
template <typename ValueType>
ostream& operator<< (ostream&, valarray<ValueType>);
template <typename ValueType>
ostream& operator<< (ostream& out, vector<ValueType> v)
{
out << "Vec[";
for (int i = 0; i < v.size() - 1; i++)
out << v[i] << ", ";
out << v[v.size() - 1] << "]";
return out;
}
template <typename ValueType>
ostream& operator<< (ostream& out, valarray<ValueType> a)
{
out << "VArr[";
for (int i = 0; i < a.size() - 1; i++)
out << a[i] << ", ";
out << a[a.size() - 1] << "]";
return out;
}
Fitness.h
:
A simple class with a couple valarray
s and a bool
. Implements a pretty-cout as well. Tested and working.
#pragma once
#include <valarray>
#include <ostream>
#include "Utils.h"
using std::valarray;
using std::ostream;
class Fitness {
public:
class FitnessNotValidException : public std::exception {};
class ValueIndexTooLargeException : public std::exception {};
class IncorrectNewValuesLength : public std::exception {};
private:
const valarray<double> weights;
bool valid;
valarray<double> values;
public:
Fitness(const valarray<double>&);
static Fitness max();
static Fitness min();
double WeightedFitness();
const valarray<double>& Weights();
bool Valid();
void Valid(bool);
void invalidate();
void validate();
const valarray<double>& Values();
void Values(int, double);
void Values(const valarray<double>&);
double Value();
void Value(double);
friend ostream& operator<< (ostream&, Fitness);
};
// Implementation for everything...
ostream& operator<<(ostream & out, Fitness fit)
{
out << "Fitness[W:" << fit.weights << ", V:" << fit.values << ", valid:" << fit.valid << "]";
return out;
}
Individual.h
:
Template class having a Fitness
member. Also implements the "pretty-cout".
#pragma once
#include <ostream>
#include <valarray>
#include "Fitness.h"
using std::ostream;
template <typename GeneType>
class Individual
{
private:
Fitness fitness;
GeneType genes;
public:
Individual(Fitness, GeneType);
Fitness& Fitness();
GeneType& Genes();
Individual<GeneType> copy();
friend ostream& operator<< (ostream&, Individual<GeneType>);
};
// Implementation for everything...
template<typename GeneType>
ostream& operator<<(ostream& out, Individual<GeneType> ind)
{
out << "Individual[G:" << ind.genes << ", F:" << ind.fitness << "]";
return out;
}
All these 3 files are included, in the same order, in the main file. If I try to print the genes and fitness of an individual all is well:
Individual<valarray<int>> ind = ind_builder.build();
cout << ind.Fitness() << endl << ind.Genes() << endl;
/*
Fitness[W:VArr[1], V:VArr[0], valid:0]
VArr[0, 0, 0, 1, 0, 1, 1, 1, 0, 1]
*/
Meaning the <<
for valarray
, Fitness
works, so I did not get anything wrong in the concept of how <<
should work. But when I try: cout << ind << endl;
error LNK2019: unresolved external symbol "class std::basic_ostream > & __cdecl operator<<(class std::basic_ostream
&,class Individual >)" (??6@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AEAV01@V?$Individual@V?$valarray@H@std@@@@@Z) referenced in function main
I don't see where the issue is. The includes seem to be in order and there is no splitting problem between .h
and .cpp
. Is there another template gotcha that I should have known? Because I have been searching for a few days for a solution aside from the ones always recommended (like moving all the code into the .h
file) with no success.