using templates in VC++ .NET

I am unable to build the following statement on the VC++ .NET, but it builds fine on VC++ 6.0.

Please advice regarding this situation or attach a snippet to overcome this situation


template<class T> typedef void (*FnPointer)(T a, bool val);

error message:
error: a typedef template is illegal
error: cannot be a template definition

suda5181Asked:
Who is Participating?
 
Jaime OlivaresSoftware ArchitectCommented:
>Is Generic pointer the best way to solve this problem currently ?
I think yes. As I told you, is a common used technique.

>I am trying to use a function template so that i can have the flexibilty, that the parameters of the function can be of any class type.
This can be acomplished with a void pointer, but you have to be careful when casting to the proper speciliazed pointer.

Also, I think you function definition could be a slower because you are trying to pass entire object (by making a copy) instead of passing pointer.
0
 
guitaristxCommented:
> error: a typedef template is illegal

This is your problem.  You can't have a typedef'd template, since you can't "define" a type that hasn't been "defined".  Without more context, I really can't help you work around this.  Can you tell me a bit more of what you're attempting to do?
0
 
suda5181Author Commented:
I am using the typedef for the function pointer, not for the function template.

the idea its like a regular function pointer declaration

typedef void (*FnPointer)(T a, bool val);

Since the first parameter "a" can be of any "class type", hence i am using a function template :

template<class T> typedef void (*FnPointer)(T a, bool val);

it works fine on vc++ 6.0, but not on VC++ .NET
0
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

 
Jaime OlivaresSoftware ArchitectCommented:
Usually, in callback functions' implementation, this is solved by using a void pointer to real data:

typedef void (*FnPointer)(void *obj, bool val);
0
 
suda5181Author Commented:
Jaimes,

Thanks for the comment.

void * is what i used to overcome this initially and it compiled fine.

But, I was wondering if there is a way I could actually use  a template.. (Maybe include a header or any syntax change  on the VC++ .NET Environment)

Are templates not supported fully on VC++ .NET?

Please advice regarding this issue

Seth
0
 
Jaime OlivaresSoftware ArchitectCommented:
I agree with comment of guitaristx, I makes no sense to me to define a typedef for a template, where data type is undefined.
I am not sure if incompatible behaviour is in either  VC++6  or  VC++.net
0
 
suda5181Author Commented:
Thanks for the comment.

Is Generic pointer the best way to solve this problem currently ?

Actually the typedef that i am using is for the function pointer.

I am trying to use a function template so that i can have the flexibilty, that the parameters of the function can be of any class type.



0
 
rcarlanCommented:
Have you considered this?

template <typename T>
struct Parm
{
      typedef void (*FnPointer)(T a, bool val);
};


It would enable you to write something like this:

void TestFnInt(int n, bool b)
{
      return;
}

void TestFnDouble(double n, bool b)
{
      return;
}

Parm<int>::FnPointer pfnInt = TestFnInt;
Parm<double>::FnPointer pfnDouble = TestFnDouble;


Radu
0
 
rcarlanCommented:
Of course, rather than using pointers to functions in conjunction with STL (or template classes in general), a much better solution is to use a functor:

template <typename T>
class Functor
{
      public:
            Functor(T a, bool val) : m_a(a), m_val(val) {}

            void operator() (void)
            {
                  // do something with m_a and m_val
            }

      private:
            T m_a;
            bool m_val;
};

You can now write this:

Functor<int> fnInt(1, true);
Functor<double> fnDouble(2, false);
fnInt();
fnDouble();


And you can also use the functor in STL algorithms.


If the implementation is already provided in existing functions and cannot be moved to a template class, but you want to introduce a layer of abstraction, you can try this:

template <typename T>
class FuncPtr
{
      public:
            typedef void (*FuncPtr_t)(T a, bool val);
            FuncPtr(FuncPtr_t fn) : m_fn(fn) {}

            void operator() (T a, bool val) {m_fn(a, val);}

      private:
            FuncPtr_t m_fn;
};

With the above, you would invoke existing functions:

void TestFnInt(int a, bool val)
{
      // do something with a and val
}

void TestFnDouble(double a, bool val)
{
      // do something with a and val
}

like so:

FuncPtr<int> pfnInt = TestFnInt;
FuncPtr<double> pfnDouble = TestFnDouble;
pfnInt(1, true);
pfnDouble(2, false);


You can combine the two, if you want to use existing (global) functions through pointers and also integrate with STL algorithms:

template <typename T>
class FuncPtr
{
      public:
            typedef void (*Type)(T a, bool val);
            FuncPtr(Type fn) : m_fn(fn), m_bParamsSpecified(false) {}
            FuncPtr(Type fn, T a, bool val) : m_fn(fn), m_a(a), m_val(val), m_bParamsSpecified(true) {}

            void operator() (T a, bool val)
            {
                  m_fn(a, val);
            }

            void operator() ()
            {
                  ASSERT(m_bParamsSpecified);
                  m_fn(m_a, m_val);
            }

      private:
            Type m_fn;
            T m_a;
            bool m_val;
            bool m_bParamsSpecified;
};


FuncPtr<int> pfnIntFunctor(TestFnInt, 1, true);
FuncPtr<double> pfnDoubleFunctor(TestFnDouble, 2, false);

pfnIntFunctor();      // invoked with 1 and true
pfnDoubleFunctor();      // invoked with 2 and false
pfnIntFunctor(3, false);    
pfnDoubleFunctor(4, true);

FuncPtr<int> pfnIntFunctorErr(TestFnInt);
pfnIntFunctorErr();      // this will fire an assert because no parameters were specified

Anyway, without having more details about what you're trying to achieve, it's difficult to recommend a solution. But, at least you now have a few type-safe alternatives for your function pointers.

Radu
0
 
suda5181Author Commented:
Thanks for the suggestion Radu
0
 
suda5181Author Commented:
Radu,

Based on your suggestion, i used a functor.

in this case i need to specify the argument list when declaring a function pointer

           eg.  FuncPtr<Int> FncPointer = function.          i need to specify the type { in this case it is int }

even if i want to pass the pointer as an argument..

           testfunction(Parm<int>::FnPointer pfnInt, bool b)

I would like to not specify the type when i pass an arguement

eg.  
          testfunction{FnPointer pfnInt, bool b)  

the reason is because.. in my program(written in Vc++ 6.0) , i wont be able to speficy the exact type in the argument list.

Please let me know if i can solve it in another way

0
 
rcarlanCommented:
What does testfunction do with pfnInt and b?
Can you post the code (something closer to the real production code, not just a stub)?
I want to assess if it's feasible to change testfunction to a template function.

Radu
0
 
suda5181Author Commented:
Since the entire implementation is huge, I am just providing a small snippet that matches the idea.

Please let me know how i can solve this. I do not wish to use "void *" instead of templates



class class1;                // I did not provide the implementation

void Function(class1* c, int i)          // Function that i will pass thru pointer
{            
return;      
}

template<class T2> typedef void (*FnPointer)(T2 c, int i);   // Cause of error

int Callfunction(FnPointer pfn)
{
      return 1;
}

void test()
{
    Callfunction((FnPointer) Function);  // passing the function pointer
}




0
 
rcarlanCommented:
Sorry, not enough.

Who will provide the parameters to the function call invoked through a pointer: test or Callfunction? I assume c is provided by test and i is provided by Callfunction.

Just want to make sure I understand correctly what you're trying to achieve.

Radu
0
 
hari4130Commented:
you are right

c is provided by test, and i is provided by callfunction.

the entire implementation is fairly long. So i just attached a snippet.

udas
0
 
rcarlanCommented:
This is the closest solution I could come up with, but it still requires explicit template parameter:

template <typename T>
class FuncCall
{
     public:
          typedef void (*FuncType)(T*, int);
          FuncCall(FuncType fn, T& a) : m_fn(fn), m_a(a) {}

          void operator() (int n)
          {
               m_fn(&m_a, n);
          }

     private:
          FuncType m_fn;
          T& m_a;
};


class A
{
      public:
            A() : n(0) {}
            int n;
};

class B
{
      public:
            B() : n(0) {}
            int n;
};

void FuncA(A* pa, int n)
{
      pa->n = n;
}

void FuncB(B* pb, int n)
{
      pb->n = n;
}


template <typename T>
void Execute(FuncCall<T>& fn)
{
      for (int i=0; i<10; ++i)
      {
            fn(i);
      }
}

void test()
{
      A a;
      B b;

      Execute(FuncCall<A>(FuncA, a));
      Execute(FuncCall<B>(FuncB, b));
}



With a 'smart' C++ comiler you should be able to code like this:

template <typename T>
class FuncPtr
{
public:
      typedef void (*FuncType)(T*, int);
      FuncPtr(FuncType fn) : m_fn(fn) {}

      void operator() (T* t, int n)
      {
            m_fn(t, n);
      }

private:
      FuncType m_fn;
};


class A
{
public:
      A() : n(0) {}
      int n;
};

class B
{
public:
      B() : n(0) {}
      int n;
};

void FuncA(A* pa, int n)
{
      pa->n = n;
}

void FuncB(B* pb, int n)
{
      pb->n = n;
}


template <typename T>
void Execute(T& t, FuncPtr<T> fn)
{
      for (int i=0; i<10; ++i)
      {
            fn(&t, i);
      }
}

#define SMART_COMPILER

void test()
{
      A a;
      B b;

#ifdef SMART_COMPILER
      Execute(a, FuncA);                  // smart compiler should deduce the template argument as being 'class A'
      Execute(b, FuncB);                  // smart compiler should deduce the template argument as being 'class B'
#else
      Execute(a, FuncPtr<A>(FuncA));      // dumb compiler requires explicit template argument (class A) for second parameter
      Execute(b, FuncPtr<B>(FuncB));      // dumb compiler requires explicit template argument (class B) for second parameter
#endif

}

I've tested with both VC6 and VC7.1 and neither is a smart enough C++ compiler :-)

Sorry,
Radu
0
 
suda5181Author Commented:
Radu,

Thanks for the snippet. I really appreciate your help.

I think i will try to work my way out using your suggestions.

Do you think i can still achieve the same complexity as above by using a simple (void *)  instead of using function templates  ??
 
   typedef void (*FnPointer)(void *c, int i);  
//By using a generic pointer instead of function templates ??

Thanks
0
 
rcarlanCommented:
Of course you can use void pointers.
The major benefits you get from the template-based solution are compile time type-checking and abstraction.
The downside is that it has a more involved calling procedure (i.e. more to type). Although, I thought that "Execute(FuncCall<A>(FuncA, a))" looked pretty good. It self-documenting: "execute a function call to FuncA for a".

Radu
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.