Различные специализации шаблона для большинства целей являются совершенно не связанными типами.Вывод аргументов шаблона может выводить шаблон и его аргументы из такого типа, но это происходит полностью во время компиляции.Не существует информации о гарантированном времени выполнения, которая может определить, является ли класс специализацией данного шаблона, являются ли два класса специализациями одного и того же шаблона и т. Д.
Так что вам нужно будет настроить способ тестированияэто самостоятельно, но ваш метод промежуточного класса - не единственный вариант.Самый простой способ - это поставить способ проверить его в базовом A
классе:
class A {
public:
virtual ~A() = default;
virtual bool is_B() const noexcept { return false; }
};
template <class T>
class B : public A {
public:
bool is_B() const noexcept override { return true; }
};
Хотя это становится немного уродливым, если есть несколько разных B-подобных категорий для проверки, ине работает, если возможно расширить A
новыми подтипами, а затем аналогичным образом протестировать эти подтипы.
Другой идеей было бы связать проверку типа с адресом объекта:
struct type_tag {
constexpr type_tag() = default;
type_tag(const type_tag&) = delete;
type_tag& operator=(const type_tag&) = delete;
};
class A {
public:
virtual ~A() = default;
virtual bool matches_type(const type_tag&) const
{ return false; }
};
inline constexpr type_tag B_tag{};
template <class T>
class B {
public:
bool matches_type(const type_tag& tag) const override
{ return &tag == &B_tag; }
};
Этот шаблон также учитывает категории подтипов, которые приходят не из одного шаблона.Это также не препятствует тому, чтобы новый класс «лгал» о своем собственном типе, если это может быть проблемой, но может быть лучше не пытаться предотвратить это, но позволить любому реализованному производному классу быть ответственным за его собственное поведение,это может означать, что он хочет действовать "почти так же, как" какой-то другой тип.