Неопределенная ссылка на неиспользуемый метод шаблона класса

Как правило, шаблоны реализуются в файлах заголовков (как указано во многих ответах в Stack Overflow), поэтому шаблон кода доступен компилятору, когда он нужен для создания нового экземпляра класса / функции. Однако в моем случае некоторые методы в моем классе-шаблоне можно использовать только для определенного типа, поэтому мой класс выглядит так:

Заголовок класса

#ifndef LEC_H
#define LEC_H

#include <iostream>

template <typename T>
class LEC
{
public:
  LEC()
  {
  }

  void func() const;

  void func2() const
  {
    std::cout << "Func 2" << std::endl;
  }
};

#endif  // LEC_H

Класс cpp

#include "lec.h"

template <typename T>
void LEC<T>::func() const
{
  std::cout << "Func: " << typeid(T).name() << std::endl;
}

template class LEC<float>;
template class LEC<double>;

Последние две строки файла cpp позволяют мне использовать func(), потому что я явно создаю экземпляр этого шаблона класса для этих двух типов. Когда я использую этот шаблон класса в программе, я могу использовать любой тип, если я не вызываю func():

#include "lec.h"

int main()
{
  LEC<float> a;
  LEC<double> b;
  a.func2();
  a.func();
  b.func2();
  b.func();
  LEC<char> c;
  c.func2();
  return 0;
}

Но поскольку компилятор недоступен для включения func() в класс LEC с типом char, я не могу выполнить c.func(), иначе я получу ошибку компилятора:

undefined reference to `LEC::func() const'

Это упрощение моего реального кода. Однако в моем коде, когда я использую LEC<char> c для создания экземпляра класса, я получаю сообщение об ошибке без вызова каких-либо методов, только путем создания класса.

  • Есть идеи, как узнать, почему этот, по-видимому, неиспользуемый метод должен быть связан?
  • Есть ли способ, чтобы компилятор (в моем случае я использую clang ++: clang версии 6.0.0-1ubuntu2) указывал, где этот метод используется в коде?
  • В противном случае, может кто-нибудь объяснить, почему это (без ссылки на неиспользуемый метод класса) работает в приведенном примере, а не в моем коде?

Редактировать Cmake выглядит так:

add_library(lec_lib SHARED lec.cpp lec.h)
add_executable(lec_main main.cpp)
target_link_libraries(lec_main lec_lib)

Следовательно, скомпилированная библиотека связана с исполняемым файлом.

Редактировать 2 Не предлагайте такие ответы, как Почему шаблоны могут быть реализованы только в файле заголовка, поскольку я уже знаю, что шаблон должен быть доступен компилятору при создании экземпляра класса для нового типа. У меня другой вопрос. Почему я могу создать экземпляр типа, для которого доступны не все реализации шаблона, если я не использую конкретные методы класса, для которых реализация шаблона не предоставляется во время создания экземпляра (в примере случая func())

Редактировать 3 Что касается предположения, что это дубликат Что такое ошибка неопределенной ссылки / неразрешенного внешнего символа и как ее исправить?. Опять же, у меня другой вопрос. Я ищу ответы о том, почему в этом примере я могу создать экземпляр LEC<char>, когда LEC<char>::func() не отображается для компилятора при компиляции основной программы. И в том случае, если это невозможно сделать и требуется связать L3C<char>::func(), как узнать, почему требуется привязка метода, пока он не используется (что происходит в моем реальном коде).

Я прочту еще раз более внимательно этот пост, который вы упомянули, но я думаю, что у меня другой вопрос.

apalomer 18.12.2018 13:47

Нет, это то же самое, вы забыли скомпилировать два файла cpp и связать их с двумя объектными файлами.

Matthieu Brucher 18.12.2018 13:47

Пожалуйста, попробуйте еще раз открыть этот вопрос. Я дал понять, что он отличается от предложенных дубликатов.

apalomer 18.12.2018 14:07

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

fieres 18.12.2018 14:10

apalomer: это может быть политика вашего конкретного компилятора, который хочет, чтобы все члены были определены. С clang ++ ваши файлы компилируются и работают нормально. Вы пробовали реализовать func () в заголовке? Если код не работает для определенного параметра шаблона, но никогда не используется, он все равно может компилироваться.

fieres 18.12.2018 14:17

@apalomer Вы не вызываете c.func () в main (), где и происходит сбой. С этим добавлением он не работает как с g ++, так и с clang ++ на моей машине. Я бы сказал, просто не делай этого.

Michael Surette 18.12.2018 15:11
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
93
0

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