параметр шаблона c ++ с объявлением карты - PullRequest
5 голосов
/ 25 ноября 2011

Что не так с этим кодом:

Заголовок:

#include <map>

using namespace std;

template<class T>
class ValueCollection
{
public:
    ValueCollection(void);

    int getValueCount(void);

    map<string, T> Values;
};

Реализация:

#include "ValueCollection.h"

ValueCollection<class T>::ValueCollection(void)
{
}

int ValueCollection<class T>::getValueCount(void)
{
    return Values.size();
}

Тест:

#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);
}

Это ошибка:

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

Ответы [ 3 ]

3 голосов
/ 25 ноября 2011

Пара проблем.

Ваша самая непосредственная ошибка компилятора вызвана неправильным синтаксисом в реализации функций-членов шаблона класса.Вы должны предварять определение члена шаблона класса ключевым словом template.То есть:

template<class T> ValueCollection<T>::ValueCollection(void)
{
}

template<class T> int ValueCollection<T>::getValueCount(void)
{
    return Values.size();
}

Есть и другая проблема, которая станет очевидной только по мере роста вашей программы.Вы не можете определить шаблонные функции или классы в одном модуле перевода и использовать их в другом месте.Компилятор должен иметь полное определение, доступное в каждой единице перевода.

Как правило, это достигается путем определения функций шаблона непосредственно в заголовочном файле, там, где они объявлены.В вашем случае:

template<class T>
class ValueCollection
{
public:
    ValueCollection(void)
    {
    }

    int getValueCount(void)
    {
        return Values.size();
    }

    map<string, T> Values;
};

Это только один способ сделать это - есть другие.Другой способ - использовать так называемый « метод включения »:

ValueCollection.h

template<class T>
class ValueCollection
{
public:
    ValueCollection(void);

    int getValueCount(void);

    map<string, T> Values;
};

#include "ValueCollection.hpp:

ValueCollection.hpp

template<class T> ValueCollection<T>::ValueCollection(void)
{
}

template<class T> int ValueCollection<class T>::getValueCount(void)
{
    return Values.size();
}

Еще один метод заключается в предоставлении нового определения для каждой единицы перевода, которая хочет использовать шаблоны, но это было бы весьма необычно.(На самом деле, я никогда не делал этого за 15 лет программирования на C ++)

3 голосов
/ 25 ноября 2011

реализация должна читать:

#include "ValueCollection.h"

template <class T>
ValueCollection<T>::ValueCollection(void)
{
}

template <class T>
int ValueCollection<T>::getValueCount(void)
{
    return Values.size();
}
0 голосов
/ 25 ноября 2011

Вам требуется template <class T> перед каждым методом в вашем файле реализации.

...