[Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 312
  • Last Modified:

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

0
suda5181
Asked:
suda5181
  • 7
  • 6
  • 3
  • +2
2 Solutions
 
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
 
Jaime OlivaresCommented:
Usually, in callback functions' implementation, this is solved by using a void pointer to real data:

typedef void (*FnPointer)(void *obj, bool val);
0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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 OlivaresCommented:
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
 
Jaime OlivaresCommented:
>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
 
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

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 7
  • 6
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now