What is wrong with this code:
Header:
#include <map>
using namespace std;
template<class T>
class ValueCollection
{
public:
ValueCollection(void);
int getValueCount(void);
map<string, T> Values;
};
Implementation:
#include "ValueCollection.h"
ValueCollection<class T>::ValueCollection(void)
{
}
int ValueCollection<class T>::getValueCount(void)
{
return Values.size();
}
Test:
#include "ValueCollection.h"
TEST(ValueCollection_TestCases, Default_Constructor_MapIsEmpty)
{
ValueCollection<int>* target = new ValueCollection<int>;
int expected = 0;
int actual = target->getValueCount();
ASSERT_EQ(expected, actual);
}
This is the error:
Error 1 error C2079: 'std::_Pair_base<_Ty1,_Ty2>::second' uses undefined class 'T' c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility 167 1 Refactor01
A couple of problems.
Your most immediate compiler error is caused by incorrect syntax in the implementation of the class template member functions. You must preface definition of a class template member with the template
keyword. To wit:
template<class T> ValueCollection<T>::ValueCollection(void)
{
}
template<class T> int ValueCollection<T>::getValueCount(void)
{
return Values.size();
}
There's another problem too, which will only become apparent later as your program grows. You can't define template functions or classes in one Translation Unit and use them in antoher. The compiler must have the complete definition available in each translation unit.
Typically, the way this is accomplished is by defining template functions directly in the header file, right where they are declared. In your case:
template<class T>
class ValueCollection
{
public:
ValueCollection(void)
{
}
int getValueCount(void)
{
return Values.size();
}
map<string, T> Values;
};
That's just one way to accomplish this -- there are others. Another way is to use the so-called "inclusion method":
template<class T>
class ValueCollection
{
public:
ValueCollection(void);
int getValueCount(void);
map<string, T> Values;
};
#include "ValueCollection.hpp:
template<class T> ValueCollection<T>::ValueCollection(void)
{
}
template<class T> int ValueCollection<class T>::getValueCount(void)
{
return Values.size();
}
Yet another method would be to supply a new definition for each translation unit that wants to use the templates, but this would be highly unusual. (In fact, I have never done this in my 15 years of C++ programming)
implementation should read:
#include "ValueCollection.h"
template <class T>
ValueCollection<T>::ValueCollection(void)
{
}
template <class T>
int ValueCollection<T>::getValueCount(void)
{
return Values.size();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With