N
nguillot
Hello.
I'm not sure I can do what I will ask you...
Let's say I've got a template class inheriting from a non template
class:
struct SData
{
virtual ~SData() {}
};
template <class T>
struct SDataContainer : public SData
{
SDataContainer(const T& o) : m_data(o) {}
T m_data;
};
Then I have a class with methods receiving a SData as parameter. It
can be a SDataContainer<T>, or other class inheriting from SData.
In the following example, the method print will deduce the type of the
data thanks to dynamic_cast:
class SPrintDataContainer
{
public:
void print(SData* pData)
{
SDataContainer<int>* pi = dynamic_cast<SDataContainer<int>*>
(pData);
if (pi != 0)
{
cout << "printing integer " << pi->m_data << endl;
return;
}
SDataContainer<bool>* pb = dynamic_cast<SDataContainer<bool>*>
(pData);
if (pb != 0)
{
cout << "printing bool " << (pb->m_data ? "true" :
"false") << endl;
return;
}
cout << "data type not handled" << endl;
}
};
So I can use that as follow:
SData* pDataInt = new SDataContainer<int>(5);
SData* pDataBool = new SDataContainer<bool>(false);
SData* pDataDouble = new SDataContainer<double>(2);
SPrintDataContainer DataPrinter;
DataPrinter.print(pDataInt);
DataPrinter.print(pDataBool);
DataPrinter.print(pDataDouble);
It will output
printing integer 5
printing bool false
data type not handled
(and produce 3 memory leaks ;-) ).
Ok.
Now, the question: is there a way to avoid the dynamic_cast and deduce
the template argument thanks to template method specialization.
I would like to write something like that:
class SPrintDataContainer_withoutDynamicCast
{
public:
template <class T>
void print(SDataContainer<T>* pData)
{
cout << "data type not handled" << endl;
}
template <>
void print(SDataContainer<int>* pData)
{
cout << "printing integer " << pData->m_data << endl;
}
template <>
void print(SDataContainer<bool>* pData)
{
cout << "printing bool " << (pData->m_data ? "true" : "false")
<< endl;
}
};
But I can't use this class like that:
SPrintDataContainer_withoutDynamicCast DataPrinter2;
DataPrinter2.print(pDataInt);
DataPrinter2.print(pDataBool);
DataPrinter2.print(pDataDouble);
**First: Is me need clear?
There is a good example of the interest of this kind of design
here:
http://www.boost.org/doc/libs/1_38_0/libs/ptr_container/test/tree_test.cpp
Here, we pass either a leaf<T> or an inner_node as a node.
And we can imagine a class that must print a tree, that receives
nodes, and according to the type (inner_node, leaf<int>,
leaf<double> ....) it must display something different.
**So: my question is: is there a way, a workaround of my sample, to
deduce the template argument of the template class when we receive an
object of the base class, in the way I suggest (template method
specialization). Maybe with proxy classes that would deduce the
template, I don't know.
Thanks in advance for you help, or critics.
Nicolas.
I'm not sure I can do what I will ask you...
Let's say I've got a template class inheriting from a non template
class:
struct SData
{
virtual ~SData() {}
};
template <class T>
struct SDataContainer : public SData
{
SDataContainer(const T& o) : m_data(o) {}
T m_data;
};
Then I have a class with methods receiving a SData as parameter. It
can be a SDataContainer<T>, or other class inheriting from SData.
In the following example, the method print will deduce the type of the
data thanks to dynamic_cast:
class SPrintDataContainer
{
public:
void print(SData* pData)
{
SDataContainer<int>* pi = dynamic_cast<SDataContainer<int>*>
(pData);
if (pi != 0)
{
cout << "printing integer " << pi->m_data << endl;
return;
}
SDataContainer<bool>* pb = dynamic_cast<SDataContainer<bool>*>
(pData);
if (pb != 0)
{
cout << "printing bool " << (pb->m_data ? "true" :
"false") << endl;
return;
}
cout << "data type not handled" << endl;
}
};
So I can use that as follow:
SData* pDataInt = new SDataContainer<int>(5);
SData* pDataBool = new SDataContainer<bool>(false);
SData* pDataDouble = new SDataContainer<double>(2);
SPrintDataContainer DataPrinter;
DataPrinter.print(pDataInt);
DataPrinter.print(pDataBool);
DataPrinter.print(pDataDouble);
It will output
printing integer 5
printing bool false
data type not handled
(and produce 3 memory leaks ;-) ).
Ok.
Now, the question: is there a way to avoid the dynamic_cast and deduce
the template argument thanks to template method specialization.
I would like to write something like that:
class SPrintDataContainer_withoutDynamicCast
{
public:
template <class T>
void print(SDataContainer<T>* pData)
{
cout << "data type not handled" << endl;
}
template <>
void print(SDataContainer<int>* pData)
{
cout << "printing integer " << pData->m_data << endl;
}
template <>
void print(SDataContainer<bool>* pData)
{
cout << "printing bool " << (pData->m_data ? "true" : "false")
<< endl;
}
};
But I can't use this class like that:
SPrintDataContainer_withoutDynamicCast DataPrinter2;
DataPrinter2.print(pDataInt);
DataPrinter2.print(pDataBool);
DataPrinter2.print(pDataDouble);
**First: Is me need clear?
There is a good example of the interest of this kind of design
here:
http://www.boost.org/doc/libs/1_38_0/libs/ptr_container/test/tree_test.cpp
Here, we pass either a leaf<T> or an inner_node as a node.
And we can imagine a class that must print a tree, that receives
nodes, and according to the type (inner_node, leaf<int>,
leaf<double> ....) it must display something different.
**So: my question is: is there a way, a workaround of my sample, to
deduce the template argument of the template class when we receive an
object of the base class, in the way I suggest (template method
specialization). Maybe with proxy classes that would deduce the
template, I don't know.
Thanks in advance for you help, or critics.
Nicolas.