views:

90

answers:

5

Rephrased Question

I found that my original question wasn't clear enough and the repliers misunderstood my problem. So let me try to clarify:

Let's say I have two classes:

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

Now I want to make a generic version of the two, so I do something like this:

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

But now I don't know how to instantiate this class:

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;  //???

Original Question:

Hi,

I have a template class that can take a function pointer or a std::function object as its parameter. All is fine until that function uses a pointer of the template class in its signature:

#include <functional>

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

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

Relevant compiler errors:

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

How do it solve this problem?

+2  A: 

C is a class template, not a class. You can't have an object of type C or a pointer to a C; you can only have objects of instantiations of C, like C<int> or C<float>.

James McNellis
+2  A: 

In this line:

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

The bolded C (emphasis added) does not specify template parameters. You should specify what type of C* this function pointer takes, by specifying a type in <> brackets.

asveikau
Thank you. I understand why the compiler is complaining. But I don't know how to solve this. C<void( * )( C<void( * )(C<???>*)>* )> obviously doesn't work. :(
What they are saying is template<typename Func> class C { public: C() {} Func m_func; }; void foo() { C<void(*)(C<int>*)> c; C<std::function<int(C<int>*)>> d; } int main(){}
Chubsdad
Yes, I understand. But I want that C* to be a pointer of its own type. ie. if the whole thing isn't a template, it would look like this: class C { void( * m_func)(C * ); };
Or this: class C { std::function<int(C*)> m_func; };
+1  A: 

Does this help?

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);
}
Chubsdad
A: 

You cannot have a recursive template.

Alexander Rafferty
Is there any kind of recursion that templates don't support?
Potatoswatter
+1  A: 

You can't name the recursive template outside itself, but you can name it inside, as the parameter list is optional in a self-reference.

The problem then becomes one of telling the template how to pass itself to "something."

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;
Potatoswatter
Thank you. I'll try this out. :)