Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > C++ Template Virtual Function

Reply
Thread Tools

C++ Template Virtual Function

 
 
Vishal
Guest
Posts: n/a
 
      11-30-2012
Hi,

I have Class A and according to my requirements the implementation of
the class is fixed. Class A manages the setting/getting of values.
The values stored can be of type integer, unsigned integer, character,
unsigned character and std::strings. The available types can grow in
the future. I'm having trouble finding a manageable way of storing
values of different types with the ability of retrieving them. The
problem area is class B's getValue method. It can't be a virtual
template method of a non template class. So, how should I provide a
unified way for class A to get a list of all the stored values that
match the tag value being passed?

I don't need to have a class B and C. If there is a better way that
only has one class, it's okay. I do want to avoid just having a bunch
of switch statements that executes different code based on different
types. This is what I think is unmanageable as new type are required.


#include<list>


class B
{
private:
unsigned long m_Tag;

public:

B(unsigned long tag) : m_Tag(tag) {}

template<typename T>
virtual int getValue(std::list<T> &val) = 0;


}; // end of class B


template<typename T>
class C : public B
{
private:
T m_Value;

public:
C(unsigned long const& tag, T const& value) : B(tag) {
m_Value = value;
}

virtual int getValue(std::list<T> &val) {
val.push_back(m_Value);
}

}; // end of class C

class A
{
private:
std::list<B> m_Collection;

public:
template<typename T>
setTagValue(unsigned long tag, T const& value) {
m_Collection.push_back(C<T>(tag, value));
}

template<typename T>
getTagValue(unsigned long const tag, std::list<T> values) {
for(auto i = m_Collection.begin(); i != m_Collection.end(); i++) {
if(i->getTag() == tag) {
i->getValue(values);
}
}
}


}; // end of class A







int main (void)
{
A collection;

collection.setTagValue(2, "hello");
collection.setTagValue(3, static_cast<int>(3));

std::list<int> values;

collection.getTagValue(3, values);
};
 
Reply With Quote
 
 
 
 
Vishal
Guest
Posts: n/a
 
      12-03-2012
On Dec 1, 2:18*am, Paavo Helde <(E-Mail Removed)> wrote:
> Vishal <(E-Mail Removed)> wrote innews:(E-Mail Removed):
>
> > Hi,

>
> > I have Class A and according to my requirements the implementation of
> > the class is fixed. *Class A manages the setting/getting of values.
> > The values stored can be of type integer, unsigned integer, character,
> > unsigned character and std::strings. *The available types can grow in
> > the future. *I'm having trouble finding a manageable way of storing
> > values of different types with the ability of retrieving them. *The
> > problem area is class B's getValue method. *It can't be a virtual
> > template method of a non template class. *So, how should I provide a
> > unified way for class A to get a list of all the stored values that
> > match the tag value being passed?

>
> There is no such thing as a virtual template function. This would require
> recompiling all classes in the class hierarchy and adding vtable slots to
> all classes whenever a new specialization happens to be called on *any*
> class in the hierarchy. This would mean some serious whole program
> analysis and would not probably work with DLL-s anyway.
>
> That said, it seems you are wanting some kind of type erasure feature. In
> principle this means to store pointers to dynamically allocated instances
> of different types in your container, and upon retrieval restore the type
> somehow. This sounds similar to boost::any, maybe you can use this.
>
> > class A
> > {
> > * * private:
> > * * *std::list<B> m_Collection;

>
> You can't have a list of base class B objects here; when storing derived
> C objects as B they would be sliced. That's why you need to store
> pointers instead. The boost::any class encapsulates this pointer
> mechanism AFAIK and hides such details from you.
>
> In any case, bear in mind that the template mechanisms are compile-time
> only and cannot dispatch the execution based on information which becomes
> available at run-time only. This probably means that if the run-time type
> of the objects is determined by a "tag", then the tag must appear as a
> template parameter in your interface, in order to avoid run-time switch
> statements.
>
> hth
> Paavo



> There is no such thing as a virtual template function. This would require
> recompiling all classes in the class hierarchy and adding vtable slots to
> all classes whenever a new specialization happens to be called on *any*
> class in the hierarchy. This would mean some serious whole program
> analysis and would not probably work with DLL-s anyway.


You are correct. I discovered the same thing when this didn't work.
It was unfortunate.


> That said, it seems you are wanting some kind of type erasure feature. In
> principle this means to store pointers to dynamically allocated instances
> of different types in your container, and upon retrieval restore the type
> somehow. This sounds similar to boost::any, maybe you can use this.


I'm familiar with boost::any. I had hoped to use it but couldn't
figure out how to avoid the type cast exception failures if the wrong
type was asked for. Since, I know that only one type will be correct
I don't want the cost of throwing exceptions to find the correct
type. I've ended up storing the type that was passed in so I could
figure out which cast to use. This avoids my issue of using a wrong
cast, but now I need a switch statement.

//Example casting
switch(a)
{
case: eType::float: cast here
}


> In any case, bear in mind that the template mechanisms are compile-time
> only and cannot dispatch the execution based on information which becomes
> available at run-time only. This probably means that if the run-time type
> of the objects is determined by a "tag", then the tag must appear as a
> template parameter in your interface, in order to avoid run-time switch
> statements.


I'm vaguely familiar with tag dispatching. How would you use tag
dispatching with getValues<T>? Would this design fix the switch
statement issue I discussed earlier? I would like to have a single
place to add new types and not change A. Is that possible with tag
dispatching?

Thanks

Vishal
 
Reply With Quote
 
 
 
 
Vishal
Guest
Posts: n/a
 
      12-03-2012
On Dec 3, 9:42*am, Paavo Helde <(E-Mail Removed)> wrote:
> Vishal <(E-Mail Removed)> wrote innews:(E-Mail Removed):
>


> I'm vaguely familiar with tag dispatching. How would you use tag
> dispatching with getValues<T>? Would this design fix the switch



I've have included an updated version of the example code that uses
boost::any.

>> It is not clear what do you want to achieve.


B::getValue shows the "switch" like statement that I want to avoid
needing to modify as new types are added.


> How do you call getValues<T>? More specifically, how do you specify T when
> calling it? How is T related to the type of the stored items?


Class B::getValue shows how I'm relating my stored type with T. Can
tag dispatch end my suffering?


struct eType
{
enum Type {
short,
long
char
};
};

class B
{
private:
unsigned long m_Tag;
boost::any m_Value;
eType::Type m_Type;

protected:
template<typename T>
eType::Type getType(void) {
if (boost::is_same<T, short>::value ) return eType::short;
if (boost::is_same<T, long >::value ) return eType::long;
if (boost::is_same<T, char >::value ) return eType::char;

return eType::char; //Should never get to this return.
}

public:
B(unsigned long tag, boost::any & value, eType::Type type)
: m_Tag(tag)
, m_Value(value)
, m_Type(type)
{
BOOST_STATIC_ASSERT(boost::is_same<T, short>::value ||
boost::is_same<T, long>::value || boost::is_same<T, char>::value);
}

template<typename T>
int getValue(std::list<T> &val) {
if ( m_Type == eType::short )
val.push_back(boost::any_cast<short>(m_Value));
if ( m_Type == eType::long ) val.push_back(boost::any_cast<long>
(m_Value));
if ( m_Type == eType::char ) val.push_back(boost::any_cast<char>
(m_Value));

return 0;
}
}; // end of class B


template<typename T>
class C : public B
{
public:
C(unsigned long const& tag, T const& value) : B(tag, value,
B::getType<T>()) {}
}; // end of class C


class A
{
private:
std::list<B> m_Collection;

public:
template<typename T>
setTagValue(unsigned long tag, T const& value) {
m_Collection.push_back(C<T>(tag, value));
}


template<typename T>
getTagValue(unsigned long const tag, std::list<T> values) {
for(auto i = m_Collection.begin(); i != m_Collection.end(); i++) {
if(i->getTag() == tag) {
i->getValue(values);
}
}
}
}; // end of class A

int main (void)
{
A collection;

collection.setTagValue(3, static_cast<int>(3));

std::list<int> values;

collection.getTagValue(3, values);
};


 
Reply With Quote
 
Vishal
Guest
Posts: n/a
 
      12-03-2012
> The getType() method does not make much sense. It just translates from T
> to the enum values. First, there is no reason for it to be a member
> function of B. Second, there is an run-time dispatch which is not needed
> as everything is known at compile-time. Typically, this kind of
> translation is done by some kind of traits class (which typically
> contains other useful stuff as well), e.g.:


Thanks for the traits example. That makes sense.


> In getValue(), it seems inner type m_Type is in no way related to the output type T.


Not correct. The inner type is comparing it's value against the
passed type.

> If the types do not match, your code converts
> the data, possibly truncating the values.


If the types don't match the code doesn't add anthing to the passed
list. So, how is the code converting data?


> If you were able to guarantee that the client code always calls getValue
> with the correct (matching) T, then it would be indeed trivial to write a
> shorter version:
>
> template<typename T>
> int getValue(std::list<T> &val) {
> * *val.push_back(boost::any_cast<T>(m_Value));
> * *return 0;
>
> }


Since it's not guaranteed, couldn't we check the types with the tag
dispatch like so?

template<typename T>
int getValue(std::list<T> &val) {
if ( m_Type == getType<T>() )
val.push_back(boost::any_cast<T>(m_Value));
return 0;
}

 
Reply With Quote
 
Jeff Flinn
Guest
Posts: n/a
 
      12-04-2012
On 12/3/2012 12:08 PM, Vishal wrote:
> On Dec 1, 2:18 am, Paavo Helde <(E-Mail Removed)> wrote:
>> Vishal <(E-Mail Removed)> wrote innews:(E-Mail Removed):
>>
>>> Hi,

>>
>>> I have Class A and according to my requirements the implementation of
>>> the class is fixed. Class A manages the setting/getting of values.
>>> The values stored can be of type integer, unsigned integer, character,
>>> unsigned character and std::strings. The available types can grow in
>>> the future. I'm having trouble finding a manageable way of storing
>>> values of different types with the ability of retrieving them. The
>>> problem area is class B's getValue method. It can't be a virtual
>>> template method of a non template class. So, how should I provide a
>>> unified way for class A to get a list of all the stored values that
>>> match the tag value being passed?

>>
>> There is no such thing as a virtual template function. This would require
>> recompiling all classes in the class hierarchy and adding vtable slots to
>> all classes whenever a new specialization happens to be called on *any*
>> class in the hierarchy. This would mean some serious whole program
>> analysis and would not probably work with DLL-s anyway.
>>
>> That said, it seems you are wanting some kind of type erasure feature. In
>> principle this means to store pointers to dynamically allocated instances
>> of different types in your container, and upon retrieval restore the type
>> somehow. This sounds similar to boost::any, maybe you can use this.
>>
>>> class A
>>> {
>>> private:
>>> std::list<B> m_Collection;

>>
>> You can't have a list of base class B objects here; when storing derived
>> C objects as B they would be sliced. That's why you need to store
>> pointers instead. The boost::any class encapsulates this pointer
>> mechanism AFAIK and hides such details from you.
>>
>> In any case, bear in mind that the template mechanisms are compile-time
>> only and cannot dispatch the execution based on information which becomes
>> available at run-time only. This probably means that if the run-time type
>> of the objects is determined by a "tag", then the tag must appear as a
>> template parameter in your interface, in order to avoid run-time switch
>> statements.
>>
>> hth
>> Paavo

>
>
>> There is no such thing as a virtual template function. This would require
>> recompiling all classes in the class hierarchy and adding vtable slots to
>> all classes whenever a new specialization happens to be called on *any*
>> class in the hierarchy. This would mean some serious whole program
>> analysis and would not probably work with DLL-s anyway.

>
> You are correct. I discovered the same thing when this didn't work.
> It was unfortunate.
>
>
>> That said, it seems you are wanting some kind of type erasure feature. In
>> principle this means to store pointers to dynamically allocated instances
>> of different types in your container, and upon retrieval restore the type
>> somehow. This sounds similar to boost::any, maybe you can use this.

>
> I'm familiar with boost::any. I had hoped to use it but couldn't
> figure out how to avoid the type cast exception failures if the wrong
> type was asked for. Since, I know that only one type will be correct
> I don't want the cost of throwing exceptions to find the correct
> type. I've ended up storing the type that was passed in so I could
> figure out which cast to use. This avoids my issue of using a wrong
> cast, but now I need a switch statement.
>
> //Example casting
> switch(a)
> {
> case: eType::float: cast here
> }
>
>
>> In any case, bear in mind that the template mechanisms are compile-time
>> only and cannot dispatch the execution based on information which becomes
>> available at run-time only. This probably means that if the run-time type
>> of the objects is determined by a "tag", then the tag must appear as a
>> template parameter in your interface, in order to avoid run-time switch
>> statements.


Have you watched the video of Sean Parent's boostcon/C++ Now talk at:

http://www.youtube.com/watch?v=_BpMYeUFXv8&feature=plcp

The recently accepted boost type erasure library by Steven Watanabe may
be useful to you.

http://steven_watanabe.users.sourcef...tml/index.html

Jeff Flinn
 
Reply With Quote
 
Vishal
Guest
Posts: n/a
 
      12-04-2012
> For reference, I repeat the getValue() code here:
>
> template<typename T>
> int getValue(std::list<T> &val) {
> if ( m_Type == eType::short ) val.push_back(boost::any_cast<short>(m_Value));
> if ( m_Type == eType::long ) val.push_back(boost::any_cast<long> (m_Value));
> if ( m_Type == eType::char ) val.push_back(boost::any_cast<char> (m_Value));
>
> return 0;
> }


Again, you are corrrect. I meant to place a double if statement.

if ( (m_Type == eType::short) && (m_Type == getType<T>() )


> Yes, if this is OK regarding your app logic, you can do this. For this
> you won't need the whole eType system though as boost::any knows its
> stored type anyway:


I must be missing something. Boost any may know what type it but the
documentation doesn't specify a way to get that information. The
examples show the follow way to determine type. I really don't want
to throw exceptions for incorrect type cast.

try
{
any_cast<const char *>(operand);
return true;
}
catch(const boost::bad_any_cast &)
{
return false;
}


 
Reply With Quote
 
Vishal
Guest
Posts: n/a
 
      12-04-2012
On Dec 4, 5:40*am, Jeff Flinn <(E-Mail Removed)> wrote:
> On 12/3/2012 12:08 PM, Vishal wrote:
>
>
>
>
>
> > On Dec 1, 2:18 am, Paavo Helde <(E-Mail Removed)> wrote:
> >> Vishal <(E-Mail Removed)> wrote innews:(E-Mail Removed):

>
> >>> Hi,

>
> >>> I have Class A and according to my requirements the implementation of
> >>> the class is fixed. *Class A manages the setting/getting of values.
> >>> The values stored can be of type integer, unsigned integer, character,
> >>> unsigned character and std::strings. *The available types can grow in
> >>> the future. *I'm having trouble finding a manageable way of storing
> >>> values of different types with the ability of retrieving them. *The
> >>> problem area is class B's getValue method. *It can't be a virtual
> >>> template method of a non template class. *So, how should I provide a
> >>> unified way for class A to get a list of all the stored values that
> >>> match the tag value being passed?

>
> >> There is no such thing as a virtual template function. This would require
> >> recompiling all classes in the class hierarchy and adding vtable slotsto
> >> all classes whenever a new specialization happens to be called on *any*
> >> class in the hierarchy. This would mean some serious whole program
> >> analysis and would not probably work with DLL-s anyway.

>
> >> That said, it seems you are wanting some kind of type erasure feature.In
> >> principle this means to store pointers to dynamically allocated instances
> >> of different types in your container, and upon retrieval restore the type
> >> somehow. This sounds similar to boost::any, maybe you can use this.

>
> >>> class A
> >>> {
> >>> * * *private:
> >>> * * * std::list<B> m_Collection;

>
> >> You can't have a list of base class B objects here; when storing derived
> >> C objects as B they would be sliced. That's why you need to store
> >> pointers instead. The boost::any class encapsulates this pointer
> >> mechanism AFAIK and hides such details from you.

>
> >> In any case, bear in mind that the template mechanisms are compile-time
> >> only and cannot dispatch the execution based on information which becomes
> >> available at run-time only. This probably means that if the run-time type
> >> of the objects is determined by a "tag", then the tag must appear as a
> >> template parameter in your interface, in order to avoid run-time switch
> >> statements.

>
> >> hth
> >> Paavo

>
> >> There is no such thing as a virtual template function. This would require
> >> recompiling all classes in the class hierarchy and adding vtable slotsto
> >> all classes whenever a new specialization happens to be called on *any*
> >> class in the hierarchy. This would mean some serious whole program
> >> analysis and would not probably work with DLL-s anyway.

>
> > You are correct. *I discovered the same thing when this didn't work.
> > It was unfortunate.

>
> >> That said, it seems you are wanting some kind of type erasure feature.In
> >> principle this means to store pointers to dynamically allocated instances
> >> of different types in your container, and upon retrieval restore the type
> >> somehow. This sounds similar to boost::any, maybe you can use this.

>
> > I'm familiar with boost::any. *I had hoped to use it but couldn't
> > figure out how to avoid the type cast exception failures if the wrong
> > type was asked for. *Since, I know that only one type will be correct
> > I don't want the cost of throwing exceptions to find the correct
> > type. *I've ended up storing the type that was passed in so I could
> > figure out which cast to use. *This avoids my issue of using a wrong
> > cast, but now I need a switch statement.

>
> > //Example casting
> > switch(a)
> > {
> > case: eType::float: *cast here
> > }

>
> >> In any case, bear in mind that the template mechanisms are compile-time
> >> only and cannot dispatch the execution based on information which becomes
> >> available at run-time only. This probably means that if the run-time type
> >> of the objects is determined by a "tag", then the tag must appear as a
> >> template parameter in your interface, in order to avoid run-time switch
> >> statements.

>
> Have you watched the video of Sean Parent's boostcon/C++ Now talk at:
>
> http://www.youtube.com/watch?v=_BpMYeUFXv8&feature=plcp
>
> The recently accepted boost type erasure library by Steven Watanabe may
> be useful to you.
>
> http://steven_watanabe.users.sourcef...re/libs/type_e...
>
> Jeff Flinn- Hide quoted text -
>
> - Show quoted text -


Thanks. Those were helpful.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to use the template member function of a template in the memberfunction of another template class? Peng Yu C++ 3 10-26-2008 03:51 PM
Virtual Template or Template Virtual pocmatos@gmail.com C++ 4 01-23-2006 08:44 PM
virtual template and virtual access for ADSL circuits Gary Cisco 1 04-28-2005 07:26 PM
function non-template versus fully specialized function template Robert Allan Schwartz C++ 1 08-09-2004 03:41 PM
virtual function and pure virtual function in the implementation of COM IK C++ 2 07-23-2004 02:55 PM



Advertisments