Я пытаюсь реализовать класс на С++, который содержит большинство функций, которые мне могут понадобиться для использования в разных иерархиях классов (проект имеет несколько разных деревьев наследования).
После прочтения и получения рекомендаций от нескольких ответов для такого рода реализации на Переполнение стека , Почему шаблоны могут быть реализованы только в заголовочном файле? Я решил реализовать это, используя файл .h и 2 разных файла .cpp. Я попытался реализовать небольшой тестовый пример, используя этот FAQ в качестве руководства. Код выглядит следующим образом:
тест.ч
#ifndef TEST_H
#define TEST_H
#include <iostream>
#include <cmath>
#include <complex>
template<typename T>
class test{
public:
static bool IsClose(const T &a, const T &b);
};
#endif
testImpl.h
#include "test.h"
template <typename T>
bool test<T>::IsClose(const T &a, const T &b){
return (std::abs(a-b) <= (1e-8 + 1e-5 * std::abs(b)));
}
testImpl.cpp
#include "testImpl.h"
template class test<int>;
template class test<double>;
main.cpp
#include "test.h"
#include <iomanip>
int main(){
std::cout << std::boolalpha << test<double>::IsClose(1e-7,1.1e-7) << std::endl;
return 0;
}
При компиляции с использованием g++ -o test main.cpp testImpl.cpp
я получаю следующую ошибку:
main.cpp: In function ‘int main()’:
main.cpp:4:36: error: ‘test’ is not a template
std::cout << std::boolalpha << test<double>::IsClose(1e-7,1.1e-7) << std::endl;
Если кто-нибудь может посоветовать мне, где я ошибаюсь, ваша помощь будет очень признательна. Заранее спасибо!! Кроме того, если есть лучший способ добиться того, что я пытаюсь сделать, ваши мысли также приветствуются по этому вопросу.
@bolov @Elliot Я изменил имя test.cpp
на testImpl.h
, но ошибка осталась.
Компилируется ли он, если вы поместите весь исходный код в один файл? Какую версию g++ вы используете? Кроме того, как предложил @Elliott, попробуйте переименовать TEST_H, чтобы не использовать начальные или конечные символы подчеркивания.
@Eugene компилируется, когда я помещаю все в один исходный файл. Я использую g++ версии 7.5.0 и пытался удалить начальные и конечные символы подчеркивания, но безрезультатно. Также я попробовал этот код как функции шаблона вместо класса шаблона, и он отлично скомпилировался.
@Elliot Я тоже изменил это в коде. Удалены начальные и конечные символы подчеркивания... Но, к сожалению, у меня все еще та же ошибка.
Я не смог воспроизвести вашу проблему. Какой у тебя процессор и ОС?
@Elliot Ubuntu 18.04 и процессор i7 8-го поколения.
@DewanArunSingh, странно. Я также использую Ubuntu 20.04 и i7 8-го поколения (i7-8550U).
Что вам дает gcc -v
?
Давайте продолжим обсуждение в чате.
Я понял это наконец. Мне нужно было сообщить компилятору, что ему нужно использовать более новую версию C++. Итак, g++ -std=c++17 -o test main.cpp testImpl.cpp
отлично скомпилировал код для меня.
Необходимость использования флага -std возникает только при использовании gcc версии 7.5.0. Все версии gcc после него работают с g++ -o test main.cpp testImpl.cpp
.
Это помогает решить проблему, но не объясняет, почему она вообще не компилировалась. Это все еще загадка (возможно, ошибка в GCC 7.5.0, известная или неизвестная). Кроме того, пожалуйста, но нет необходимости благодарить кого-либо в своем ответе. Stackoverflow должен быть очень тупым. =П
@ Эллиот, кажется, ты был прав, ЭТО ошибка в gcc 7.5.0. Я попробовал тот же код с gcc 10.1.0, и он работал без флага -std.
поместите весь код вашего шаблона в заголовки. Только явные реализации специализации шаблона должны быть в cpp