Класс шаблона только со статическими методами Реализация с использованием файла .cpp, дающего ошибку

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

После прочтения и получения рекомендаций от нескольких ответов для такого рода реализации на Переполнение стека , Почему шаблоны могут быть реализованы только в заголовочном файле? Я решил реализовать это, используя файл .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;

Если кто-нибудь может посоветовать мне, где я ошибаюсь, ваша помощь будет очень признательна. Заранее спасибо!! Кроме того, если есть лучший способ добиться того, что я пытаюсь сделать, ваши мысли также приветствуются по этому вопросу.

поместите весь код вашего шаблона в заголовки. Только явные реализации специализации шаблона должны быть в cpp

bolov 23.12.2020 03:39

@bolov @Elliot Я изменил имя test.cpp на testImpl.h, но ошибка осталась.

Dewan Arun Singh 23.12.2020 03:49

Компилируется ли он, если вы поместите весь исходный код в один файл? Какую версию g++ вы используете? Кроме того, как предложил @Elliott, попробуйте переименовать TEST_H, чтобы не использовать начальные или конечные символы подчеркивания.

Eugene 23.12.2020 03:56

@Eugene компилируется, когда я помещаю все в один исходный файл. Я использую g++ версии 7.5.0 и пытался удалить начальные и конечные символы подчеркивания, но безрезультатно. Также я попробовал этот код как функции шаблона вместо класса шаблона, и он отлично скомпилировался.

Dewan Arun Singh 23.12.2020 04:02

@Elliot Я тоже изменил это в коде. Удалены начальные и конечные символы подчеркивания... Но, к сожалению, у меня все еще та же ошибка.

Dewan Arun Singh 23.12.2020 04:30

Я не смог воспроизвести вашу проблему. Какой у тебя процессор и ОС?

Elliott 23.12.2020 04:30

@Elliot Ubuntu 18.04 и процессор i7 8-го поколения.

Dewan Arun Singh 23.12.2020 04:36

@DewanArunSingh, странно. Я также использую Ubuntu 20.04 и i7 8-го поколения (i7-8550U).

Elliott 23.12.2020 04:39

Что вам дает gcc -v?

Elliott 23.12.2020 04:45

Давайте продолжим обсуждение в чате.

Dewan Arun Singh 23.12.2020 04:49
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
10
138
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я понял это наконец. Мне нужно было сообщить компилятору, что ему нужно использовать более новую версию 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 должен быть очень тупым. =П

Elliott 23.12.2020 05:04

@ Эллиот, кажется, ты был прав, ЭТО ошибка в gcc 7.5.0. Я попробовал тот же код с gcc 10.1.0, и он работал без флага -std.

Dewan Arun Singh 23.12.2020 05:45

Другие вопросы по теме