Я использую мой класс в качестве параметра шаблона одного из его родительских классов, и этот родительский класс использует его в аргументе шаблона (хотя sizeof ()).
И компилятор выдаёт мне:
ошибка: неполный тип 'Invoker :: workerClass {aka MyClass}', используемый во спецификаторе вложенного имени
Покакласс хорошо определен в файле.Я предполагаю, что это потому, что дочерний класс не был создан в момент создания базового класса, но такого рода вещи случаются с CRTP и проблем нет.
Причина, по которой яиспользовать дочерний класс в аргументе шаблона - это сделать другой вызов функции, если дочерний класс имеет или не имеет определенной функции.
Вот минимальный код для тестирования
/* Structure similar to boost's enable if, to use
SFINAE */
template <int X=0, class U = void>
struct test {
typedef U type;
};
enum Commands {
Swim,
Fly
};
/* Structure used for template overloading,
as no partial function template specialization available */
template<Commands T>
struct Param {
};
template <class T>
class Invoker
{
public:
typedef T workerClass;
workerClass *wc() {
return static_cast<workerClass*>(this);
}
template <Commands command>
void invoke() {
invoke2(Param<command>());
}
/* If the child class has those functions, call them */
/* Needs template paramter Y to apply SFINAE */
template<class Y=int>
typename test<sizeof(Y)+sizeof(decltype(&workerClass::fly))>::type
invoke2(Param<Fly>) {
wc()->fly();
}
template<class Y=int>
typename test<sizeof(Y)+sizeof(decltype(&workerClass::swim))>::type
invoke2(Param<Swim>) {
wc()->shoot();
}
template<Commands command>
void invoke2(Param<command>) {
/* Default action */
printf("Default handler for command %d\n", command);
}
};
template <class T, class Inv = Invoker<T> >
class BaseClass : public Inv
{
public:
template<Commands command>
void invoke() {
Inv::template invoke<command>();
}
};
class MyClass : public BaseClass<MyClass>
{
public:
void swim() {
printf("Swimming like a fish!\n");
}
/* void fly(); */
};
void testing() {
MyClass foo;
foo.invoke<Fly>(); /* No 'void fly()' in MyClass, calls the default handler */
foo.invoke<Swim>(); /* Should print the swimming message */
}
Ошибка возникает в строке:
typename test<sizeof(Y)+sizeof(decltype(&workerClass::fly))>::type
Итак, есть ли компилятор, который поддерживает это, или это явно указано стандартом как недопустимое использование шаблонов?Должен ли я изменить способ, которым я делаю это, и найти способ обойти?CRTP дает мне надежду, что код может быть действительным, но я не уверен.
Если это действительно невозможно, то почему именно, и почему CRTP работает?