| | |
Meta-programming, templates, virtual member functions
Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved |
•
•
Join Date: Sep 2008
Posts: 31
Reputation:
Solved Threads: 0
Hello all,
Before anything else, this issue is also posted at: http://www.cplusplus.com/forum/general/7518/
I have a structure similar to the one below.I miss a lot of information about the specific template parameters, so I would need something like what is in the code. This code does not compile because we cannot have templatized virtual member functions. Does anyone have a clever idea how to solve this? The result I want is to get through the specialized operator() of B<O,true>.
Before anything else, this issue is also posted at: http://www.cplusplus.com/forum/general/7518/
I have a structure similar to the one below.I miss a lot of information about the specific template parameters, so I would need something like what is in the code. This code does not compile because we cannot have templatized virtual member functions. Does anyone have a clever idea how to solve this? The result I want is to get through the specialized operator() of B<O,true>.
c++ Syntax (Toggle Plain Text)
#include <iostream> using namespace std; class SomeClass; /* In the real code I have SomeClass< T, P, Q> * and this is not known when the compiler reaches A,B and C*/ struct OtherClass{ int i; double d; OtherClass(int ii, double dd):i(ii),d(dd){}; }; /* My idea of A is this, although it is not * possible to have a virtual template function */ class A{ public: template<class K> virtual void operator()(K input )=0; }; template<int L, bool M, class S> struct B : public A{ template<class K> void operator()(K input ){ cout << "Inside B" << endl; }; }; template<class S> struct B<0, true, S> : public A{ template<class K> void operator()(K input ){ cout << "Inside B<0,true>"<< endl; }; }; /* This class creates and stores an object of type B (or one of the specializations). * But L and M are unknown so I created A to store the B object here * K is also unknown here. */ class C{ A* object; public: C(){ /* * Get some data from files and according * to this data construct a B specialized object. */ object = new B< 0, true, SomeClass>(); }; void go(){ /* * Later, I want to call B, that was stored through the interface A */ (*object)(new OtherClass(0,2)); } }; int main(void){ C* c = new C(); c->go(); return 0; };
•
•
•
•
Well, so far, nobody replied. But if I am freaking out someone I can remove it. Why is it a waste of time? And, if you consider it a waste of time what are you doing here? Are you being paid or something?
If we were paid we wouldn't care
Chris
Last edited by Freaky_Chris; Feb 5th, 2009 at 12:56 pm.
Knowledge is power -- But experience is everything
•
•
Join Date: Sep 2008
Posts: 31
Reputation:
Solved Threads: 0
Well, I know you re not being paid. However, that doesn't give you the right to be rude, as I think you were in your first post. You're just one more specialist in something, like there are a lot of them out there. Anyway thank you for your attention. I am pretty sure that people do waht I did, without even warning.
So, I will remove this post from here and if later I still need I will close it on the other site and open it here.
Cheers,
Rui
So, I will remove this post from here and if later I still need I will close it on the other site and open it here.
Cheers,
Rui
•
•
Join Date: Nov 2008
Posts: 392
Reputation:
Solved Threads: 72
Well first off, I accept that you didn't get any replies at the previous forum, so I will accept that you should re-post. (I might have waited another day or so but that is minor). Given that, I would like to comment on your problem, and actually ask a few quesitons really.
First off: C++ forbids template virtual functions of any sort. You can normally code round that in a slightly ugly way. Several methods around depending on the probelms (many based on encapsulating the function in a template class)
Second: I think that you are trying to do some kind of template dispatch ???? If this is the case then you should look at the boost mpl.
An effective method of doing what I thnk you want is this:
The above code basically, sets an internal state variable object, that is an effective virtual object. That results in one extra level of dereference. [I think it was Andrei Alexandrescu who said that when faced with a problem the solution is to add a level of dereference.] This is such a case. You have moved from method to object, and then it works.
Note that I have not fixed any of the delete operators, so this leaks memory. It does almost what you want, and has runtime flexiblity. If this is not what you are after please post again. BUT this time make your example shorter and the question slightly more explicit.
First off: C++ forbids template virtual functions of any sort. You can normally code round that in a slightly ugly way. Several methods around depending on the probelms (many based on encapsulating the function in a template class)
Second: I think that you are trying to do some kind of template dispatch ???? If this is the case then you should look at the boost mpl.
An effective method of doing what I thnk you want is this:
c++ Syntax (Toggle Plain Text)
#include <iostream> class A { public: static void call() { std::cout<<"This is A"<<std::endl;} }; class B { public: static void call() { std::cout<<"This is B"<<std::endl;} }; class Base { public: virtual void go() {std::cout<<"Base"<<std::endl; } }; template<typename T> class hold : public Base { public: hold() : Base() {} void go() { T::call(); } }; class C { Base* object; public: C() : object(new hold<A>()) {} template<typename T> void setHold() { delete object; object=new hold<T>; } void go() { object->go(); } }; int main() { C cobj; cobj.go(); cobj.setHold<B>(); cobj.go(); return 0; }
The above code basically, sets an internal state variable object, that is an effective virtual object. That results in one extra level of dereference. [I think it was Andrei Alexandrescu who said that when faced with a problem the solution is to add a level of dereference.] This is such a case. You have moved from method to object, and then it works.
Note that I have not fixed any of the delete operators, so this leaks memory. It does almost what you want, and has runtime flexiblity. If this is not what you are after please post again. BUT this time make your example shorter and the question slightly more explicit.
Last edited by StuXYZ; Feb 7th, 2009 at 9:34 am.
experience is the most expensive way to learn anything
•
•
Join Date: Sep 2008
Posts: 31
Reputation:
Solved Threads: 0
Hello, and thank you for the reply. Yes, what I am trying to do is some kind of template dispatch. I could have made the example a bit shorter maybe but not much. I need, in fact, the template parameters at the class B (A or B in your example). I think I have two main problems: first, I only know the classes' template parameters in runtime (thus I cannot store a A<> or B<> object and I need a holder); the second, is that the function that is going to be called takes an argument which type must be deduced, using a template in the function (this template function is the one that would be virtual). I tried to get a way of propagating this argument's type untill the place where class B is instanciated, avoiding this problematic templated function, but I could not do it.
Rui
Rui
•
•
Join Date: Nov 2008
Posts: 392
Reputation:
Solved Threads: 72
I am a bit lost: You cannot create a class from template parameters that are not known at compile time. For example
You can't have
As for adding parameters that are deduced at runtime, that is ok
do that dispatch first , then do the class dispatch (via hold).
In that case put the parameters into hold. OR do class then the dispatch on runtime, boost::any is a quick way to impliment that.
c++ Syntax (Toggle Plain Text)
template<int N> class A { };
A<i> and since you will only have created explicit instances. e.g. A<0> , A<1>. You can do dispatch of a known sequence. e.g 1-10 but that is your lot with templates. As for adding parameters that are deduced at runtime, that is ok
do that dispatch first , then do the class dispatch (via hold).
In that case put the parameters into hold. OR do class then the dispatch on runtime, boost::any is a quick way to impliment that.
experience is the most expensive way to learn anything
•
•
Join Date: Sep 2008
Posts: 31
Reputation:
Solved Threads: 0
•
•
•
•
You cannot create a class from template parameters that are not known at compile time
That's why I am having such problems. I have one class, say C, that, in the constructor, reads a file and according to this file will aggregate a object, say B, which has an int template parameter and implements the desired behavior for C. This way I can associate the file contents with different specializations of B (B<0>, B<1>, etc). The first problem is that in C I don't know which specialization of B will be stored. The second problem is that the function in B is supposed to get an argument which type is also unknown, therefore needs to be a template function, not allowing the virtualization.•
•
•
•
As for adding parameters that are deduced at runtime, that is ok
do that dispatch first , then do the class dispatch (via hold).
In that case put the parameters into hold. OR do class then the dispatch on runtime, boost::any is a quick way to impliment that.
cpp Syntax (Toggle Plain Text)
#include <iostream> #include "boost/any.hpp" using namespace std; class SomeClass; struct OtherClass{ int i; double d; OtherClass(int ii, double dd):i(ii),d(dd){}; }; struct Base{ virtual double call(boost::any in)=0; }; template<int L, bool M, class S, class T> struct B : Base{ double call(boost::any in ){ cout << "Inside B" << endl; return 0;}; }; template<class S,class T> struct B<0, true, S,T>:Base{ double call(boost::any in){ cout << "Inside B<0,true> and obj.i is "<< boost::any_cast<T*>(in)->i<< endl; return 0;}; }; template<class Q> class C{ Base* i; public: template< class T > C( T* t ){ i = new B< 0, true, SomeClass, T>(); }; template<class T> void go( T* t ){ i->call( boost::any(t) ); } }; int main(void){ typedef C<SomeClass> CS; CS* c = new CS(new OtherClass(2,1));//dummy object c->go(new OtherClass(0,2)); return 0; };
Related to propagation of the argument type: for this I am using a templatized constructor in C and a dummy argument to deduce the type. I have enough information to do this like in a regular function: C<ArgType>(). Is there a way to do something like this or to avoid having to propagate the arg type untill de B objects?
Thank you
![]() |
Other Threads in the C++ Forum
- Previous Thread: Makefile on unix to ? on windows
- Next Thread: XmlNode and changing the text of an element
| Thread Tools | Search this Thread |
api array arrays based beginner binary bitmap c++ c/c++ calculator char char* class classes coding compile compiler console conversion count data database delete desktop developer directshow dll dynamiccharacterarray email encryption error file forms fstream function functions game getline google graph homeworkhelp homeworkhelper iamthwee ifstream input int integer lib linkedlist linux list loop looping loops map math matrix memory multiple news node number numbertoword output parameter pointer problem program programming project proxy python random read recursion recursive reference return rpg sorting string strings struct template templates test text tree unix url vector video visual visualstudio win32 windows winsock word wordfrequency wxwidgets





