Существует ли строка template class Derived<int>;
в заголовочном файле, который снова включен в несколько исходных файлов?
В этом случае, vtable и методы класса Derived<int>
будут существовать в нескольких объектах-файлы.И компоновщик должен выяснить, что делать с этими несколькими копиями.
Как компилятор и компоновщик должны разрешать это в соответствии со стандартом c ++, я не уверен в этом.Но, как правило, мне все равно, поскольку копии обычно должны выглядеть одинаково.
Но чтобы избежать этой проблемы, вы должны поместить extern template class Derived<int>;
в заголовочный файл и template class Derived<int>;
ровно в 1 единицу компиляции (иначе. source-file)
EDIT (чтобы отразить ваше разделение кода на «file.hpp» и «file.cpp»):
Я немного поиграл с clang-6(Это последняя версия, которая у меня есть)
Для меня предупреждение относится к типу «Если вы сделаете X, произойдет Y».Но это не значит, что у произошло.
В этом случае Y - это несколько vtables, и это произойдет, только если вы поместите template class Derived<int>;
в несколько исходных файлов, чего вы не делаете.
Предупреждение срабатывает для каждого template class Derived<int>;
в ваших источниках, поэтому, если вы видите только одно предупреждение, будет только один vtable.
Но есть способ избавиться от предупреждения: неиметь явное создание экземпляра и полагаться на то, что компилятор неявно создает экземпляр класса.
Для этого вы должны поместить все определения вашего шаблона в заголовочный файл.Поэтому переместите определения:
template<typename T>
bool Derived<T>::func(void) {return true;}
template<typename T>
Derived<T>::Derived(void) {}
в заголовочный файл и удалите extern template class Derived<int>;
и template class Derived<int>;