Рекурсивный шаблон?

#c #templates #function #stl

#c #шаблоны #функция #stl

Вопрос:

Перефразированный вопрос

Я обнаружил, что мой первоначальный вопрос был недостаточно ясен, и ответчики неправильно поняли мою проблему. Итак, позвольте мне попытаться прояснить:

Допустим, у меня есть два класса:

 struct C { void(*m_func)(C*); };
struct D { std::function<void(D*)> m_func; };
  

Теперь я хочу создать общую версию из двух, поэтому я делаю что-то вроде этого:

 template<typename Func>
struct G
{
Func m_func;
};
  

Но теперь я не знаю, как создать экземпляр этого класса:

 G<void(*)(G*)> c;  //error
G<std::function<void(G*)>> d;  //error

G<void(*)( G<void(*)(G<???>*)> *)> c;  //???
G<std::function<void( G<std::function<void(G<???>*)>> *)>> d;  //???
  

Оригинальный вопрос:

Привет,

У меня есть шаблонный класс, который может принимать указатель на функцию или объект std::function в качестве своего параметра. Все в порядке, пока эта функция не использует указатель на класс template в своей подписи:

 #include <functional>

template<typename Func>
class C
{
public:
    C() {}
    Func m_func;
};

void foo()
{
    C<void(*)(C*)> c;
    C<std::function<int(C*)>> d;
}
  

Соответствующие ошибки компилятора:

 error C2955: 'C' : use of class template requires template argument list
error C3203: 'function' : unspecialized class template can't be used as a template argument for template parameter 'Func', expected a real type
error C2955: 'std::tr1::function' : use of class template requires template argument list
  

Как это решает эту проблему?

Ответ №1:

Вы не можете назвать рекурсивный шаблон вне самого себя, но вы можете назвать его внутри, поскольку список параметров необязателен при самостоятельной ссылке.

Тогда проблема заключается в том, чтобы указать шаблону, как передать себя «чему-то».

 template< typename T >
struct fptr_taking_type {      // this template is essentially a function
    typedef void (*type)( T ); // from types to types, the result being
};                             // the typedef

template< typename T >
struct stdfn_taking_type {
    typedef function< void (*)( T ) > type;
};

template< template< typename > class F >
struct G {
    typename F< G * >::type m_func; // this declares the member variable
};

...

G< fptr_taking_type > q;
  

Ответ №2:

C это шаблон класса, а не класс. У вас не может быть объекта типа C или указателя на C ; у вас могут быть только объекты экземпляров C , такие как C<int> или C<float> .

Ответ №3:

В этой строке:

 C<void(*)(C *)> c;

Выделенный жирным шрифтом C (выделено мной) не определяет параметры шаблона. Вы должны указать, какой тип C* принимает указатель на эту функцию, указав тип в <> скобках.

Комментарии:

1. Спасибо. Я понимаю, почему компилятор жалуется. Но я не знаю, как это решить. C<void( * )( C<void( * )(C<???>*)>* )> очевидно, что это не работает. 🙁

2. Они говорят, что шаблон<функция имени типа> класса C { public: C() {} Функция m_func; }; void foo() { C<void( )(C<int> )> c; C<std::function<int(C<int>*)>> d; } int main(){ }

3. Да, я понимаю. Но я хочу, чтобы C * был указателем своего собственного типа. т. е. если все это не является шаблоном, это выглядело бы так: class C { void( * m_func)(C * ); };

4. Или это: class C { std::function<int(C*)> m_func; };

Ответ №4:

Помогает ли это?

 void foo1(){}

template<typename Func> 
class C 
{ 
public: 
    C(Func f) : m_func(f) {} 
    Func m_func;
    C<Func> *mp;                 // it is a pointer,
}; 

void foo() 
{ 
    C<void (*)(void)> c (foo);
} 

int main(){
    C<void (*)(void)> c(foo);
}
  

Ответ №5:

У вас не может быть рекурсивного шаблона.

Комментарии:

1. Существует ли какой-либо вид рекурсии, который шаблоны не поддерживают?