Resolving template parameters

S

stefan.bruckner

Hi,

I am looking for a way to achieve the following. I've tried a couple
of things, but they all ended up being too complicated:

I have a templated class A. I want another class B to be able to call
a method defined in A's base class which at runtime determines the
template parameters (I know ahead what is allowed) and calls a
templated member function B with A's template parameters.

I'm imagining something like this - I know that it can't work like
this, but I would like to achieve a similarly simple syntax:

class Base
{
public:
virtual void call(...) = 0;
}

template <class T1,class T2>
class A : public Base
{
public:
void call(...)
{
if (typeid(T1) == ...)
...
else if (...)
...
else if (...)
...
}
}


class B
{
public:

void x()
{
Base *pSomePtr = ...;
pSomePtr->call(this,&B::y);
};

template <class T1,class T2>
void y()
{
// do stuff
};
};

Any help on how I could realize this would be greatly appreciated .

Thanks,
Stefan
 
J

John Harrison

Hi,

I am looking for a way to achieve the following. I've tried a couple
of things, but they all ended up being too complicated:

I have a templated class A. I want another class B to be able to call
a method defined in A's base class which at runtime determines the
template parameters (I know ahead what is allowed) and calls a
templated member function B with A's template parameters.

I'm imagining something like this - I know that it can't work like
this, but I would like to achieve a similarly simple syntax:

class Base
{
public:
virtual void call(...) = 0;
}

template <class T1,class T2>
class A : public Base
{
public:
void call(...)
{
if (typeid(T1) == ...)
...
else if (...)
...
else if (...)
...
}
}


class B
{
public:

void x()
{
Base *pSomePtr = ...;
pSomePtr->call(this,&B::y);
};

template <class T1,class T2>
void y()
{
// do stuff
};
};

Any help on how I could realize this would be greatly appreciated .

Thanks,
Stefan

This works for me, and it isn't retricted to a known set of template
parameters. But it doesn't pass the member function to be called to the
call method. I wasn't sure if that was part of your requirements or not.

john


#include <iostream>

class B;

class Base
{
public:
virtual void call(B* b) = 0;
};

class B
{
public:

void x(Base *pSomePtr)
{
pSomePtr->call(this);
};

template <class T1,class T2>
void y()
{
std::cout << typeid(T1).name() << ' ' << typeid(T2).name() << '\n';
};
};

template <class T1, class T2>
class A : public Base
{
public:
void call(B* b)
{
b->y<T1, T2>();
}
};

int main()
{
A<int, double> a;
B b;
b.x(&a);
}
 
P

Piyo

John said:
This works for me, and it isn't retricted to a known set of template
parameters. But it doesn't pass the member function to be called to the
call method. I wasn't sure if that was part of your requirements or not.

john


#include <iostream>

class B;

class Base
{
public:
virtual void call(B* b) = 0;
};

class B
{
public:

void x(Base *pSomePtr)
{
pSomePtr->call(this);
};

template <class T1,class T2>
void y()
{
std::cout << typeid(T1).name() << ' ' << typeid(T2).name() << '\n';
};
};

template <class T1, class T2>
class A : public Base
{
public:
void call(B* b)
{
b->y<T1, T2>();
}
};

int main()
{
A<int, double> a;
B b;
b.x(&a);
}

Darn, you beat me to it!! :) Interestingly enough, we came up
with the same solution. BTW, I forgot (so I went and included
it in my solution) do you need to do ->template in the call
to member function y()? (See below).


--------------------------------------------------------------
// Modifying your example and removing ellipsis since
// it is too vague for me to work with. WLOG,
// assuming all your functions are have void arguments.

// forward declaration required.
class B;

// Good Stuff here. Keep
class Base
{
public:
// I am deducing you want this to apply a member function to
// an instance of class B
virtual void call( B *b ) =0;
}

// had to move the definition of B up due to dependency.
class B
{
public:

void x();

template <class T1,class T2>
void y()
{
T1 *a = new T1();
T2 *b = new T2();
// leak memory!! WooHoo!
};
};

template <class T1,class T2>
class A : public Base
{
public:
// this needs to be virtual right?
virtual void call( B *b )
{
// you do not need to switch on typeid. since the virtual
// function will do it for you automagically I am also assuming
// that this "call" function will call y.
// if you need to remap T1 and T2 to some other type
// do NOT switch on typeid, use a template type function instead.
b->template y<T1,T2>();
}
}

inline void B::x()
{
Base *pSomePtr = new A<int, float>();
pSomePtr->call( this );
// WooHoo!! Leak more memory!!
};

// Honestly though, with such a cyclic dependency between
// class A and B, are you sure you want to do this at all?
 
S

stefan.bruckner

This works for me, and it isn't retricted to a known set of template
parameters. But it doesn't pass the member function to be called to the
call method. I wasn't sure if that was part of your requirements or not.

john

#include <iostream>

class B;

class Base
{
public:
virtual void call(B* b) = 0;

};

class B
{
public:

void x(Base *pSomePtr)
{
pSomePtr->call(this);
};

template <class T1,class T2>
void y()
{
std::cout << typeid(T1).name() << ' ' << typeid(T2).name() << '\n';
};

};

template <class T1, class T2>
class A : public Base
{
public:
void call(B* b)
{
b->y<T1, T2>();
}

};

int main()
{
A<int, double> a;
B b;
b.x(&a);



}

Thanks for your reply. Sorry I forgot to mention this, but
unfortunately it is one of the key requirements to specify the member
function to be called, so you can do somthing like this:

class B
{
public:

void x(Base *pSomePtr, Base *pSomeOtherPtr)
{
pSomePtr->call(this,&B::dosomething);
pSomePtr->call(this,&B::dosomethingelse);
pSomeOtherPtr->call(this,&B::doanotherthing);
};


template <class T1,class T2>
void dosomething()
{
std::cout << typeid(T1).name() << ' ' <<
typeid(T2).name() << '\n';
};

template <class T1,class T2>
void dosomethingelse()
{
std::cout << typeid(T1).name() << ' ' <<
typeid(T2).name() << '\n';
};

template <class T1,class T2>
void doanotherthing()
{
std::cout << typeid(T1).name() << ' ' <<
typeid(T2).name() << '\n';
};
};

If it wasn't for that, I guess your solution would be ideal. The
problem with what I want is - of course - that it's impossible using
member function pointers. So I'm looking for something that would
provide a similarly nice syntax.

--Stefan
 
J

John Harrison

Piyo said:
Darn, you beat me to it!! :) Interestingly enough, we came up
with the same solution. BTW, I forgot (so I went and included
it in my solution) do you need to do ->template in the call
to member function y()? (See below).

I can't remember the rules for ->template. I know it's purpose is to
disambiguate the syntax for the compiler, so I add it if the compiler is
complaining. If the compiler isn't complaining I figure there is nothing
to disambiguate.

john
 
S

stefan.bruckner

I can't remember the rules for ->template. I know it's purpose is to
disambiguate the syntax for the compiler, so I add it if the compiler is
complaining. If the compiler isn't complaining I figure there is nothing
to disambiguate.

john

Thanks for your replies. Maybe I should explain the scenario in a bit
more detail:

Class Base is actually something called a Resource, which can be an
Array, Image, Volume, etc.

Class A is one type of Resource, e.g a Volume. The voxels of the
volume can have different types (char,int,float,...) and number of
components (1,2,...).

Class B wants to perform some processing on a resource, for any type
and any number of components. The algorithm will, in general, be
independent of type and components (but there also might be the need
for partial specialization for some types/number of components).

All class B gets is a pointer to a resource and now it wants to call
some member of the resource class which determines the actual type of
resource and its voxel type and components and calls and appropriate
templated member which I want to specify. The actual implementation of
the algorithm is performance critical, so everything should be
statically typed after this point.

--Stefan
 
P

Piyo

Thanks for your reply. Sorry I forgot to mention this, but
unfortunately it is one of the key requirements to specify the member
function to be called, so you can do somthing like this:

class B
{
public:

void x(Base *pSomePtr, Base *pSomeOtherPtr)
{
pSomePtr->call(this,&B::dosomething);
pSomePtr->call(this,&B::dosomethingelse);
pSomeOtherPtr->call(this,&B::doanotherthing);
};


template <class T1,class T2>
void dosomething()
{
std::cout << typeid(T1).name() << ' ' <<
typeid(T2).name() << '\n';
};

template <class T1,class T2>
void dosomethingelse()
{
std::cout << typeid(T1).name() << ' ' <<
typeid(T2).name() << '\n';
};

template <class T1,class T2>
void doanotherthing()
{
std::cout << typeid(T1).name() << ' ' <<
typeid(T2).name() << '\n';
};
};

If it wasn't for that, I guess your solution would be ideal. The
problem with what I want is - of course - that it's impossible using
member function pointers. So I'm looking for something that would
provide a similarly nice syntax.

--Stefan

This is the best I could do with the existing example
code. I could not figure out how to deal with function
template-ids since I am not sure if they can be easily
substituted for class template-ids. Thus, I had to
manually, instantiate the member function down below.

BTW, based on your real specs, I will post a different
idea for you. This one I think does not fit well BUT
you can learn a lot from this, I believe.

------------------------------------------------------
#include <boost/function.hpp>

class B;
class Base
{
public:
typedef boost::function<void (B*)> Functor;
virtual void call( B *b, Functor func ) =0;
virtual void getFunctor() = 0;
};

// had to move the definition of B up due to dependency.
class B
{
public:
void x();

template<class T1, class T2>
void y()
{
}

template<class T1, class T2>
void z()
{
}
};

template <class T1,class T2>
class A : public Base
{
public:
virtual void call( B *b, boost::function<int (B*)> func )
{
// apply functor
func( b );
}
}

inline void B::x()
{
Base *pSomePtr = new A<int, float>();
pSomePtr->call( this, &B::y<int,float> );
pSomePtr->call( this, &B::z<int,float> );
};
 
P

Piyo

Thanks for your replies. Maybe I should explain the scenario in a bit
more detail:

Class Base is actually something called a Resource, which can be an
Array, Image, Volume, etc.

Class A is one type of Resource, e.g a Volume. The voxels of the
volume can have different types (char,int,float,...) and number of
components (1,2,...).

Class B wants to perform some processing on a resource, for any type
and any number of components. The algorithm will, in general, be
independent of type and components (but there also might be the need
for partial specialization for some types/number of components).

All class B gets is a pointer to a resource and now it wants to call
some member of the resource class which determines the actual type of
resource and its voxel type and components and calls and appropriate
templated member which I want to specify. The actual implementation of
the algorithm is performance critical, so everything should be
statically typed after this point.

--Stefan

So here is my new suggestion. Based on this description, you seem to
be pushing the responsibility of knowing how to apply the algorithm
properly onto the algorithm. This is not the best way to do it. Since
your algorithm is independent of type and components, you can
encapsulate it as a templated functor. Then inside each concrete
Resource, you instantiate as many as Processors as you need for
each component you need to process and do the processing.

I sure hope this helps :)

-------------------------------------------------------------------
#include <boost/function.hpp>

template<typename T1>
class Proc
{
public:
T1 operator()( const T1 &val )
{
// process
}
};

class Resource
{
virtual void applyProc() = 0;
};

template<typename T1>
class Array
{
virtual void applyProc()
{
Proc<T1> processor;
for( unsigned int i=0; i < m_internal.size(); ++i )
{
m_internal = processor( m_internal );
}
}
private:
std::vector<T1> m_internal;
};

template<typename T1, typename T2>
class Image
{
virtual void applyProc()
{
Proc<T1> processor1;
Proc<T2> processor2;
for( unsigned int i=0; i < m_internal.size(); ++i )
{
m_first = processor1( m_first );
m_second = processor2( m_second );
}
}
private:
std::vector<T1> m_first;
std::vector<T2> m_second;
};

template<typename T1, typename T2, typename T3>
class Volume
{
// .. you get the picture
};
 
S

stefan.bruckner

Thanks for your replies. Maybe I should explain the scenario in a bit
more detail:
Class Base is actually something called a Resource, which can be an
Array, Image, Volume, etc.
Class A is one type of Resource, e.g a Volume. The voxels of the
volume can have different types (char,int,float,...) and number of
components (1,2,...).
Class B wants to perform some processing on a resource, for any type
and any number of components. The algorithm will, in general, be
independent of type and components (but there also might be the need
for partial specialization for some types/number of components).
All class B gets is a pointer to a resource and now it wants to call
some member of the resource class which determines the actual type of
resource and its voxel type and components and calls and appropriate
templated member which I want to specify. The actual implementation of
the algorithm is performance critical, so everything should be
statically typed after this point.

So here is my new suggestion. Based on this description, you seem to
be pushing the responsibility of knowing how to apply the algorithm
properly onto the algorithm. This is not the best way to do it. Since
your algorithm is independent of type and components, you can
encapsulate it as a templated functor. Then inside each concrete
Resource, you instantiate as many as Processors as you need for
each component you need to process and do the processing.

I sure hope this helps :)

-------------------------------------------------------------------
#include <boost/function.hpp>

template<typename T1>
class Proc
{
public:
T1 operator()( const T1 &val )
{
// process
}

};

class Resource
{
virtual void applyProc() = 0;

};

template<typename T1>
class Array
{
virtual void applyProc()
{
Proc<T1> processor;
for( unsigned int i=0; i < m_internal.size(); ++i )
{
m_internal = processor( m_internal );
}
}
private:
std::vector<T1> m_internal;

};

template<typename T1, typename T2>
class Image
{
virtual void applyProc()
{
Proc<T1> processor1;
Proc<T2> processor2;
for( unsigned int i=0; i < m_internal.size(); ++i )
{
m_first = processor1( m_first );
m_second = processor2( m_second );
}
}
private:
std::vector<T1> m_first;
std::vector<T2> m_second;

};

template<typename T1, typename T2, typename T3>
class Volume
{
// .. you get the picture



};- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -


Well ... hmmmm ... the problem is that different algorithms are
performed on resources from basically all over the place. A plugin to
the application might implement a specific algorithms, for example. In
your solution, the basic problem remains:

Lets say, I now have Proc1, Proc2 and Proc3, all do different things.
At runtime, any one of them could be applied to a resource.

So I would need to pass an instance of Proc1, Proc2, or, Proc3 to
applyProc -- but that doesn't work because I don't know which
instance, since I don't know the template parameters of the resource.
 
P

Piyo

Piyo wrote:
Darn, you beat me to it!! :) Interestingly enough, we came up
with the same solution. BTW, I forgot (so I went and included
it in my solution) do you need to do ->template in the call
to member function y()? (See below).
I can't remember the rules for ->template. I know it's purpose is to
disambiguate the syntax for the compiler, so I add it if the compiler is
complaining. If the compiler isn't complaining I figure there is nothing
to disambiguate.
john
Thanks for your replies. Maybe I should explain the scenario in a bit
more detail:
Class Base is actually something called a Resource, which can be an
Array, Image, Volume, etc.
Class A is one type of Resource, e.g a Volume. The voxels of the
volume can have different types (char,int,float,...) and number of
components (1,2,...).
Class B wants to perform some processing on a resource, for any type
and any number of components. The algorithm will, in general, be
independent of type and components (but there also might be the need
for partial specialization for some types/number of components).
All class B gets is a pointer to a resource and now it wants to call
some member of the resource class which determines the actual type of
resource and its voxel type and components and calls and appropriate
templated member which I want to specify. The actual implementation of
the algorithm is performance critical, so everything should be
statically typed after this point.
--Stefan
So here is my new suggestion. Based on this description, you seem to
be pushing the responsibility of knowing how to apply the algorithm
properly onto the algorithm. This is not the best way to do it. Since
your algorithm is independent of type and components, you can
encapsulate it as a templated functor. Then inside each concrete
Resource, you instantiate as many as Processors as you need for
each component you need to process and do the processing.

I sure hope this helps :)

-------------------------------------------------------------------
#include <boost/function.hpp>

template<typename T1>
class Proc
{
public:
T1 operator()( const T1 &val )
{
// process
}

};

class Resource
{
virtual void applyProc() = 0;

};

template<typename T1>
class Array
{
virtual void applyProc()
{
Proc<T1> processor;
for( unsigned int i=0; i < m_internal.size(); ++i )
{
m_internal = processor( m_internal );
}
}
private:
std::vector<T1> m_internal;

};

template<typename T1, typename T2>
class Image
{
virtual void applyProc()
{
Proc<T1> processor1;
Proc<T2> processor2;
for( unsigned int i=0; i < m_internal.size(); ++i )
{
m_first = processor1( m_first );
m_second = processor2( m_second );
}
}
private:
std::vector<T1> m_first;
std::vector<T2> m_second;

};

template<typename T1, typename T2, typename T3>
class Volume
{
// .. you get the picture



};- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -


Well ... hmmmm ... the problem is that different algorithms are
performed on resources from basically all over the place. A plugin to
the application might implement a specific algorithms, for example. In
your solution, the basic problem remains:

Lets say, I now have Proc1, Proc2 and Proc3, all do different things.
At runtime, any one of them could be applied to a resource.

So I would need to pass an instance of Proc1, Proc2, or, Proc3 to
applyProc -- but that doesn't work because I don't know which
instance, since I don't know the template parameters of the resource.

The problem is you cannot pass Proc1, Proc2 or Proc3 since they are
Template-ids and not real functions. Another problem you are
encountering is the ability to determine template parameters from the
NON-template base class. There is a lot of mixing of compile-time and
run-time polymorphism here which spells trouble.
 
P

Piyo

If this does not help lead you to a solution, I guess it is beyond
my knowledge to solve this.

--------------------------------------------------------------
#include <vector>
#include <boost/any.hpp>

class ProcBase
{
public:
virtual ~ProcBase() {}
virtual boost::any operator()( boost::any val ) =0;
};

template<typename T1>
class Proc1 : public ProcBase
{
public:
virtual ~Proc1() {}
virtual boost::any operator()( boost::any val )
{
return boost::any( process(boost::any_cast<T1>( val )) );
}
private:
T1 process( T1 v )
{
return T1();
}
};

template<typename T1>
class Proc2 : public ProcBase
{
public:
virtual ~Proc2() {}
virtual boost::any operator()( boost::any val )
{
return boost::any( process(boost::any_cast<T1>( val )) );
}
private:
T1 process( T1 v )
{
return T1();
}
};

enum ProcType
{
kProc1, kProc2
};

template<typename T>
ProcBase *ProcFactory( ProcType t )
{
switch( t )
{
case kProc1:
return new Proc1<T>();
case kProc2:
return new Proc2<T>();
}
return NULL;
}


class Resource
{
public:
virtual ~Resource() {}
virtual void applyProc( ProcType type1, ProcType type2 ) = 0;
};

template<typename T1>
class Array : public Resource
{
public:
virtual ~Array() {}
virtual void applyProc( ProcType t, ProcType )
{
ProcBase * processor = ProcFactory<T1>( t );
for( unsigned int i=0; i < m_internal.size(); ++i )
{
m_internal =
boost::any_cast<T1>((*processor)( m_internal ));
}
}
private:
std::vector<T1> m_internal;
};

template<typename T1, typename T2>
class Image : public Resource
{
public:
virtual ~Image() {}
virtual void applyProc( ProcType t1, ProcType t2 )
{
ProcBase * processor1 = ProcFactory<T1>(t1);
ProcBase * processor2 = ProcFactory<T2>(t2);
for( unsigned int i=0; i < m_first.size(); ++i )
{
m_first =
boost::any_cast<T1>( (*processor1)( m_first ));
}
for( unsigned int i=0; i < m_second.size(); ++i )
{
m_second =
boost::any_cast<T2>( (*processor2)( m_second ));
}
}
private:
std::vector<T1> m_first;
std::vector<T2> m_second;
};

int
main()
{
Image<float,float> i;
i.applyProc( kProc1, kProc2 );
}
 
S

stefan.bruckner

(e-mail address removed) wrote:
Piyo wrote:
Darn, you beat me to it!! :) Interestingly enough, we came up
with the same solution. BTW, I forgot (so I went and included
it in my solution) do you need to do ->template in the call
to member function y()? (See below).
I can't remember the rules for ->template. I know it's purpose is to
disambiguate the syntax for the compiler, so I add it if the compiler is
complaining. If the compiler isn't complaining I figure there is nothing
to disambiguate.
john
Thanks for your replies. Maybe I should explain the scenario in a bit
more detail:
Class Base is actually something called a Resource, which can be an
Array, Image, Volume, etc.
Class A is one type of Resource, e.g a Volume. The voxels of the
volume can have different types (char,int,float,...) and number of
components (1,2,...).
Class B wants to perform some processing on a resource, for any type
and any number of components. The algorithm will, in general, be
independent of type and components (but there also might be the need
for partial specialization for some types/number of components).
All class B gets is a pointer to a resource and now it wants to call
some member of the resource class which determines the actual type of
resource and its voxel type and components and calls and appropriate
templated member which I want to specify. The actual implementation of
the algorithm is performance critical, so everything should be
statically typed after this point.
--Stefan
So here is my new suggestion. Based on this description, you seem to
be pushing the responsibility of knowing how to apply the algorithm
properly onto the algorithm. This is not the best way to do it. Since
your algorithm is independent of type and components, you can
encapsulate it as a templated functor. Then inside each concrete
Resource, you instantiate as many as Processors as you need for
each component you need to process and do the processing.
I sure hope this helps :)
-------------------------------------------------------------------
#include <boost/function.hpp>
template<typename T1>
class Proc
{
public:
T1 operator()( const T1 &val )
{
// process
}
};
class Resource
{
virtual void applyProc() = 0;
};
template<typename T1>
class Array
{
virtual void applyProc()
{
Proc<T1> processor;
for( unsigned int i=0; i < m_internal.size(); ++i )
{
m_internal = processor( m_internal );
}
}
private:
std::vector<T1> m_internal;
};
template<typename T1, typename T2>
class Image
{
virtual void applyProc()
{
Proc<T1> processor1;
Proc<T2> processor2;
for( unsigned int i=0; i < m_internal.size(); ++i )
{
m_first = processor1( m_first );
m_second = processor2( m_second );
}
}
private:
std::vector<T1> m_first;
std::vector<T2> m_second;
};
template<typename T1, typename T2, typename T3>
class Volume
{
// .. you get the picture
};- Hide quoted text -
- Show quoted text -- Hide quoted text -
- Show quoted text -

Well ... hmmmm ... the problem is that different algorithms are
performed on resources from basically all over the place. A plugin to
the application might implement a specific algorithms, for example. In
your solution, the basic problem remains:
Lets say, I now have Proc1, Proc2 and Proc3, all do different things.
At runtime, any one of them could be applied to a resource.
So I would need to pass an instance of Proc1, Proc2, or, Proc3 to
applyProc -- but that doesn't work because I don't know which
instance, since I don't know the template parameters of the resource.

The problem is you cannot pass Proc1, Proc2 or Proc3 since they are
Template-ids and not real functions. Another problem you are
encountering is the ability to determine template parameters from the
NON-template base class. There is a lot of mixing of compile-time and
run-time polymorphism here which spells trouble.


Exactly right, this mix is the problem but unfortunately unavoidable
(at least, I don't see a way) in the context of the whole application:
the flexibility of run-time polymorphismus is needed but at the level
of an actual algorithm it has to be broken due to performance reasons.
I think your last approach seems viable and I'll probably go for
something similar.

Thanks for your help,
Stefan
 
G

Grizlyk

I am looking for a way to achieve the following. I've tried a couple
of things, but they all ended up being too complicated:

I have a templated class A. I want another class B to be able to call
a method defined in A's base class which at runtime determines the
template parameters (I know ahead what is allowed) and calls a
templated member function B with A's template parameters.

I'm imagining something like this - I know that it can't work like
this, but I would like to achieve a similarly simple syntax:

class Base
{
public:
virtual void call(...) = 0;
}

virtual ~Base(){}
};
template <class T1,class T2>
class A : public Base
{
public:
void call(...)
{
if (typeid(T1) == ...)
...
else if (...)
...
else if (...)
...

Instead of "if (typeid(T1) == ...)" try

template <class T1>
class Derived: public Base
{
public:
void call(...);
};


template <class T1,class T2>
class A : public Derived<T1>
{
};

--
Maksim A. Polyanin
http://grizlyk1.narod.ru/cpp_new

"In thi world of fairy tales rolls are liked olso"
/Gnume/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top