Ответ 1
Немного изобретенный, но вот механизм, который, по крайней мере, работает.
Основная идея - скрыть A
и не наследовать напрямую от него. Вместо этого вы можете в значительной степени полагаться на mixins и объединить несколько классов в детекторе, с помощью которого вы можете специализироваться SomeClass
.
Недостатком является то, что классы, подобные B
, становятся более заумными, и я не уверен, что это стоит в конце дня. Прямые специализации, вероятно, лучше.
Как говорится, вот рабочий пример:
#include <iostream>
#include <string>
#include <utility>
using namespace std;
class ADerivedFactory {
struct A {
string name() { return "A"; }
};
template<typename T>
struct Detector: T { using type = A; };
public:
template<template<typename> class C>
using type = Detector<C<A>>;
};
template<typename T>
struct AT : T {};
template<typename T>
struct BT : T {
string name() { return "B"; }
};
using A = ADerivedFactory::type<AT>;
using B = ADerivedFactory::type<BT>;
struct C {
string name() { return "C"; }
};
template<typename T>
struct SomeClass {
using Type = T;
};
template<template<typename> class C>
struct SomeClass<ADerivedFactory::type<C>>
{
using Type = typename ADerivedFactory::type<C>::type;
};
int main(int, char**)
{
SomeClass<A>::Type el1;
SomeClass<B>::Type el2;
SomeClass<C>::Type el3;
cout << el1.name() << "," << el2.name() << "," << el3.name() << endl;
}
Посмотрите и запустите wandbox.