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>.

#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;
};

So who do you want to answer it or are you happy wasting the time of two sets of people?

Chris

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? :)

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? :)

This is my point, we are not paid. This means we volunteer out time to help provide you with a solution in which somebody on another site is already discussing in his/her own time. Meaning the same topics get covered multiple times on different forums wasting more peoples time. No doub you will find somone such as Salem is a member of both forums, and he may well refuse to post in either, despite the fact he is perhaps one of the most valuable people to you.

If we were paid we wouldn't care

Chris

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

Sorry if I come across rude. Yes alot of people do it, and they also get a LOT of stick for it thats for sure.

Chris

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:

#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. 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.

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

I am a bit lost: You cannot create a class from template parameters that are not known at compile time. For example

template<int N>
class A
{ };

You can't have 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.

You cannot create a class from template parameters that are not known at compile time

Well, I know this :) 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.

I am not sure I understood this part. In the meanwhile I have a (ugly) solution already, using boost::any you mencioned. I found a way to propagate the argument's type untill the constructor of C where I can build the B specializations passing the argument type, which will then be used in boost::any_cast<ArgType>. The current code model is this:

#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

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.