У меня есть базовый класс с членом шаблона, который в некоторых случаях явно специализирован. Производный класс дополнительно специализирует член шаблона базового класса. Смысл этого заключается в том, что различные специализации члена шаблона «логически» выполняют одну и ту же работу, адаптируясь к конкретной ситуации. Базовый класс предоставляет некоторые шаблонные специализации, которые выполняют задачу в некоторых случаях, производный класс должен «распространить» ту же задачу на другие случаи, дополнительно специализируя член шаблона.
Вот минимальный пример, иллюстрирующий проблемы, с которыми я сталкиваюсь.
#include <iostream>
struct A {
template <int i>
void dosomething();
void show();
};
template<>
void A::dosomething<0>()
{
std::cout << "0 in A" << std::endl;
}
void A::show()
{
dosomething<0>();
}
struct B : A {
// Without the following declaration:
// error: template-id ‘dosomething<1>’ for ‘void B::dosomething()’
// does not match any template declaration
template <int i>
void dosomething();
};
template<>
void B::dosomething<1>()
{
std::cout << "1 in B" << std::endl;
}
int main()
{
A x;
x.dosomething<0>();
B y;
y.dosomething<0>(); // Link error!
y.show();
y.dosomething<1>();
return 0;
}
Член шаблона A::dosomething()
явно специализирован для i=0
в базовом классе. Код для шаблона генерируется в явном виде и вызывается в элементе A::show()
.
Первая проблема, которую я обнаружил:
А) Без дублированного объявления
template <int i>
void dosomething();
внутри определения B
, код не компилируется, с ошибкой:
template-id ‘dosomething<1>’ for ‘void B::dosomething()’
does not match any template declaration.
Почему предыдущее объявление в базовом классе A
не отображается?
B) Приведенный выше код вызывает ошибку связи:
undefined reference to `void B::dosomething<0>()'
Ошибка из-за вызова y.dosomething<0>()
в основном. Этого можно избежать, позвонив вместо этого y.A::dosomething<0>()
. Почему dosomething<0>()
явно невидимо в случае B
?