Порядок объявления шаблонов C ++ - PullRequest
2 голосов
/ 02 ноября 2011

Я пытаюсь скомпилировать минимальный пример, который создает шаблон класса. Пример компилируется нормально при определенном порядке деклараций сохраняется, но в противном случае происходит сбой.

temp.h:

#include <iostream> 
template <bool display>
class test {
    public:
    void sayHi(); 
};

temp.cpp:

#include "temp.h"
template <bool display>
void  test<display>::sayHi () {
    if (display) std::cout << "Hi";
}

main.cpp:

#include <iostream>
#include "temp.h"
int main () {
    test<true> myobject;
    myobject.sayHi();
    return 0;
}

Это стандарт того, как включать классы. В GCC 4.4.6 это завершается с ошибкой main.cpp :(. text + 0x3a): неопределенная ссылка на `test :: sayHi () '

Однако, пример компилируется, когда я делаю #include "temp.cpp" вместо #include "temp.h" в main.cpp файл, так что компилятор сначала читает объявление класса в temp.h, затем видит содержимое файла temp.cpp и только потом содержимое файла main.cpp.

Когда я использую не шаблонные классы, все работает нормально, включая только файлы .h в main.cpp - что здесь не так? Обратите внимание, что temp.cpp включен в моем Makefile, так что он определенно не должен быть забыт компилятором. Спасибо за любую помощь.

Ответы [ 2 ]

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

См. Статью C ++ FAQ Lite [35.12] Почему я не могу отделить определение своего класса шаблонов от его объявления и поместить его в файл .cpp? .

Определение (он же тело) метода sayHi() должно быть в заголовке temp.h или в другом включенном файле; полный код необходим при создании экземпляра test<true>.

1 голос
/ 02 ноября 2011

При использовании шаблонов объявление и определение должны находиться в одном файле. Вы можете сделать это, поместив весь свой код в один файл (и сделав определения функций встроенными или нет, это зависит от вас), или сделав объявление и определения по отдельности, но , включая файл определений внизу .h файл .

Так было бы

tmp.h:

#include <iostream> 
template <bool display>
class test {
    public:
    void sayHi(); 
};

#include "tmp.cpp"

, tmp.cpp и main.cpp остаются неизменными (но вы не даете tmp.cpp компилятору для компиляции, поскольку он включен в tmp.h).

Многие люди называют файлы с определениями шаблонных функций в них расширением .template вместо расширения .cpp (оно позволяет вам знать, что его не нужно компилировать, плюс выглядит менее странно, чем включение файла .cpp), но тебе не нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...