Вынести метод шаблонного класса в .cpp

Рейтинг: 20Ответов: 3Опубликовано: 05.05.2011

Как вынести метод шаблонного класса из хэдера в cpp ?

Ответы

▲ 15Принят

Необходимо помнить, что шаблон порождает код класса только тогда, когда вы употребляете этот шаблон в программе с конкретными параметрами. Это означает, что нельзя скомпилировать модуль содержащий просто шаблон класса. Шаблон — это еще не тип (в C#, напротив, угловые скобки говорят о типе Generic). Таким образом, реализация метода должна быть в том модуле, где этот метод используется, иначе получите Unresolved symbol. Вот пример, который скомпилировался в MSVS 2008:

foo.h:

#pragma once

template<class T>
class Foo 
{
public:
    T bar(T a) const;
};

main.cpp

#include "foo.h"

template<class T>
T Foo<T>::bar(T a) const
{
    return a;
} 


int main(int argc, char *argv[])
{
    Foo<int> a;
    int b = a.bar(3);
    return 0;
}

Очевидно, в данном примере это равносильно варианту, когда реализация метода расположена в заголовочном файле.

А вообще, если у Вас возникла такая задача, стоит задуматься, на верном ли Вы пути, так сказать :)

▲ 7

Если Вам известно с какими типами будет инстанцироватся данный метод к шаблонном классе, то можно вынести эти специализации. Например, вот так:

foo.h

#pragma once
template<class T>
class Foo {
public:
    T bar(T a) const;
};

foo.cpp

template<>
int Foo<int>::bar(int a) const {
    return a;
}

main.cpp

#include "foo.h"
int main(int argc, char *argv[])
{
    Foo<int> a;
    int b = a.bar(3);
    return 0;
}

При этом, инстанцирование (точнее говоря вызов метода bar) с любым другим типом отличным от int будет приводить к ошибке.

▲ 7

Вот очень элегантный метод, сам юзал: http://www.gamedev.ru/code/tip/?id=5303

// main.cpp
#include "Templ.h"

int main() {
    Templ<int> templ(0);
    Templ<float> templF(0.0f);
    Templ<double> templD(0.0);
    return 0;
}

// Templ.h
#pragma once

template <typename T>
class Templ {
public:
    Templ(T t);
private:
    T x;
};

// Templ.cpp
#include "Templ.h"

template Templ<int>;
template Templ<float>;

template <typename T>
Templ<T>::Templ(T t) : x(t) {
}