C++: 2 templates vs. 1 template specialization on complex class - c++

I have a custom rather complex data structure with this form:
class Root;
class Tree {
public:
... // lots of members here, child access etc
ExactBar *bar() { return mBar; }
ExactQux *qux() { return mQux; }
private:
... // lots of members here
ExactBar *mBar;
ExactQux *mQux;
};
class Root : public Tree { // root manages the memory for all tree nodes!
...
private:
MemorySpace<Tree> mNodes;
MemorySpace<ExactBar> mBars;
MemorySpace<ExactBar> mQuxs;
};
The purpose of the program is to build the tree for which it requires the exact types above. This requires massive amounts of memory and I'm literally stretched to the 32-bit limit. So I want to, once the tree is built, convert the whole tree to an inexact type which is not only faster, but takes much less memory.
But of course I would like to keep the functionality that Tree offers with its methods, and of course other algorithms that work on Tree. So writing a new class is out of the question. So templates seem very appropriate here. However, I'm wondering about two ways of writing the new, templated class. One obvious way is
template <typename Bar, typename Qux> class Tree {
public:
... // lots of members here, child access etc
Bar *bar() { return mBar; }
Qux *qux() { return mQux; }
private:
... // lots of members here
Bar *mBar;
Qux *mQux;
};
template <typename Bar, typename Qux> class Root : public Tree<Bar, Qux> {
...
private:
MemorySpace<Tree> mNodes;
MemorySpace<Bar> mBars;
MemorySpace<Qux> mQuxs;
};
However this definition seems a bit awkward. I mean, I know I will never use Tree<InexactBar, ExactQux> for instance. Is this bad practice? Sure, you can also solve the long name with a typedef but still. Another solution I thought about is this:
template <typename Exactness> class Tree;
template <> class Tree<Exact> {
public:
... // lots of members here, child access etc
ExactBar *bar() { return mBar; }
ExactQux *qux() { return mQux; }
private:
... // lots of members here
ExactBar *mBar;
ExactQux *mQux;
};
// ... similar for Inexact
Which method is preferable, are there any patterns or anti-patterns or ripple effects doing this that I should be aware of? Thanks!!

Here's another option, that minimizes the number of template parameters and the amount of duplicated code:
struct Exact
{
typedef ExactBar BarType;
typedef ExactQux QuxType;
};
struct Inexact
{
typedef InexactBar BarType;
typedef InexactQux QuxType;
};
template <typename Exactness> class Tree {
public:
typedef typename Exactness::BarType Bar;
typedef typename Exactness::QuxType Qux;
... // lots of members here, child access etc
Bar *bar() { return mBar; }
Qux *qux() { return mQux; }
private:
... // lots of members here
Bar *mBar;
Qux *mQux;
};
This is similar to policy-based design. Of course you still have to templatize all your other functions that deal with the Tree type, so there's still a ripple effect. Although you could partially dodge the ripple effect like so:
template <typename Exactness> class TTree {
... // lots of members
};
typedef TTree<Exact> Tree; // same name as before!
typedef TTree<Inexact> InexactTree;

Another option in addition to #John's is to do explicit instantiation of your template. That is, do not include the template code into your header, but include it in a separate .cpp, and add there an explicit lines on what types do you instantiate with:
template class Tree<ExactBar, ExactQux>;
template class Tree<InexactBar, InexactQux>;
This way the compiler will not link any code using any other instantiation.
If you are pretty sure that these are the only instantiations you would ever need, then this has an additional advantage of decreased compilation time. However, this makes extending the code more difficult: you will have to modify the same .cpp if you want to add new instantiations. This is why I would suggest you using this only if you are pretty sure that you will have the full control on possible instantiations and that the number of this instantiations will not be large.

Related

Unknown Method Return Type with Polymorphic Template Classes in C++

I have been struggling to figure out how to implement the following classes. Essentially what I am trying to achieve is the following:
- The main class is for a Matrix
- The data should be stored external to the Matrix object
- The Matrix_Data should be able to support both float and double types
I've been trying to work on figuring out how to implement with templates, but I cannot seem to figure it out. This gives a general idea of my intent:
template <typename T>
class Matrix {
private:
IMatrix_Data* m_data;
...
}
class IMatrix_Data {
XXX Get_Data(); // <== The return type should be float or double, as appropriate
...
}
Can someone please give me some suggestions and some guidance?
UPDATE:
I have updated the class following #ruslo's suggestion. The problem that I'm now facing is that changing the Matrix and Matrix_Data into template classes causes a chain effect to a large number of classes. I admit that my experience with templates is very limited --- perhaps I'm going about this the wrong way, or perhaps this is the right way but it just looks wrong to me.
Basically, it would seem that any class which then uses a Matrix, or the data stored in a matrix needs to be a template class. I know that I can clean up the appearance of the code with typedef (or using statements), but I don't think that will change anything in terms of the hierarchy of classes, will it?
As an example of some classes which I have that use Matrix:
template <typename T>
class Vector : Matrix<T>
template <typename T>
class Input { // <- this class is intended to be used as a base class for runtime polymorphism
Vector<T>::DataType Get_Data();
/* Rest of class */
};
class Parameterized_Input{ // <- this class is intended to be used as a base class for runtime polymorphism
};
template <typename T>
class Input_Iterator {
/* ...
*/
std::stack<std::vector<Input<T>* >::iterator > parent_nodes; // Part of the iteration algo
}
I'm feeling rather confused here --- this is a little beyond anything I've done before and I'm hoping someone can help point me in the right direction here, both in terms of the implementation as well as any suggestions for improving the design.
For example, as I noted in the code above, the class Input is intended to be an abstract base class, to allow runtime polymorphism. Derived classes will implement this interface (and possibly Parameterized_Input) to create different types of Inputs. However, since the return type of the inputs is the same as that of the Matrix_Data -- i.e. unknown type T right now -- it seems that I will need to make every derived class into a template as well.
Unfortunately, at this time, I feel that I need the flexibility of using either a float for performance or double for precision, depending on the circumstances. If I could rule one of these out, then it would certainly simplify everything.
The alternative -- without templates, almost appears to be simpler in the big picture (based on my possible faulty understanding):
class Matrix{
IMatrix_Data* m_data;
/* ... */
}
class IMatrix_Data{
/* ... */
template <typename T>
Get_Data(int _row,int _col) { return static_cast<T>( this->ncols * _col + _row ); }
}
namespace matrix_data {
class MD_Double : public IMatrix_Data{
/* ... */
}
class MD_Double : public IMatrix_Data{
/* ... */
}
I've tried to provide enough information above, but if there's anything missing, please let me know and I'll be happy to provide additional clarification and/or information.
Thanks and regards,
Shmuel
Return value of GetData can be template parameter:
template <class T>
class MatrixImpl {
public:
typedef T DataType;
DataType GetData();
};
template <class T>
class Matrix {
public:
typedef MatrixImpl<T> Impl;
typedef typename Impl::DataType DataType;
DataType GetData() {
return data_->GetData();
}
private:
Impl* data_;
};

Container implementation for complex type

I'm trying to come up with a container wrapper which stores data of the following types: bool, int, double, std::string. In addition I have a complex type which I need to store in the container. Let's call it Foo. For the sake of simplicity we'll say that Foo contains a list of ints.
My container class currently wraps an ugly and complex container type which I get from a c api. When I'm finish manipulating the data in the container, I need to copy it back to the api. It uses unions and linked lists. It is possible that I can copy this data into, for example, a std::list, but this might cause performance issues which present themselves at a later date. Therefore, my container class is not dependant on how data is actually stored in memory.
Here's a quick idea of how my container looks:
template <class T>
class Cont
{
public:
Cont(ISetter<T>* setter)
: _setter(setter)
{
}
void sillyFunction(T t)
{
(*_setter)(t,0);
}
private:
...
ISetter<T>* _setter;
};
So I use a helper setter class which handles the nitty gritty of the memory. I have a number of these class but the ISetter will give you an idea of what I'm doing.
In order to deal with the Foo type, which is also stored by the c api in a rather bizarre way, I have arrived at the following setter. Again, this is just a rough example.
class IFoo
{
public:
virtual int getMember() = 0;
};
class Foo2: public IFoo
{
public:
virtual int getMember(){ return 1;} // dummy
};
template<typename T> class ISetter{};
template<> class ISetter<IFoo*>
{
public:
virtual void operator()(IFoo* value, int index) = 0;
};
template<typename T> class Setter{};
template<> class Setter2<Foo2*>: public ISetter<IFoo*>
{
public:
virtual void operator()(IFoo* value, int index)
{
_list[index] = dynamic_cast<Foo2*>(value);
}
private:
std::vector<Foo2*> _list;
};
So I handle my Foo as an interface called IFoo. The Setter2 implementation deals with the setting in memory of my list of Foos. Setter1, missing below, deals with the ugly c api memory.
Here's an idea of these class in practice:
Foo2* f = new Foo2();
ISetter<IFoo*>* setter = new Setter2<Foo2*>();
Cont<IFoo*>* container = new Cont<IFoo*>(setter);
container->sillyFunction(f);
When dealing with ints, for example, I do something like this instead:
int i = 10;
ISetter<int>* setter = new Setter1<int>();
Cont<int>* container = new Cont<int>(setter);
container->sillyFunction(i);
So, my question is if you think this is a good approach and what improvements you might recommend.
I use shared pointers instead of raw pointers.
I would create a single simple Foo wrapper class which can look up members data from the C API, and present it as a coherent class. No need for messing about with interfaces, virtual functions or inheritance for that. Just a single class will do.
So for each "Foo"-entry in the C API, you create a single Foo wrapper.
Then you have simple, well-behaved type representing individual instances of the data stored in your C library.
Now just take that and put it in a std::vector.
struct Foo {
Foo(<handle-or-pointer-to-library-data>);
// member functions for retrieving member data from the C API
};
std::vector<int>
std::vector<bool>
std::vector<std::string>
std::vector<Foo>
As I understand your problem, that would be a simple and efficient solution.
I would change it a little. Consider to remove all this Setter virtual-ism from your code. One of goal to introduce Templates were to have alternative to virtual-ism:
template <class T, class Setter>
class Cont
{
public:
Cont(Setter setter = Setter())
: _setter(setter)
{
}
void sillyFunction(T t)
{
_setter(t,0);
}
private:
...
Setter _setter;
};
And its simple usage:
template <class IType, class Type>
class Setter2_Virtual
{
public:
void operator()(IType* value, int index)
{
_list[index] = dynamic_cast<Type*>(value);
}
private:
std::vector<Type*> _list;
};
Cont<IFoo*, Setter2_Virtual<IFoo, Foo2> > container;
container.sillyFunction(f);
I concentrated on Setters - but maybe you can do the same with IFoo/Foo stuff as well.
Just an idea - you do not obliged to use it after all.

Add subclasses of templated base-class to container without super-base-class?

I'm trying to create a vector (or any STL container, really) that could hold a set of various objects that are subclasses of one specific type. The problem is that my base class is templated.
From what I can tell, I have to create an interface/abstract super base class (not sure what the preferred C++ terminology is). I'd prefer not to do this, and just use my (templated) abstract base class. Below is some example code.
Basically, is there a way not to require the WidgetInterface? Someway to tell the compiler to ignore template requirements? If I must have WidgetInterface, am I going the right way with the following?
#include <vector>
#include "stdio.h"
enum SomeEnum{
LOW = 0,
HIGH = 112358
};
// Would like to remove this WidgetInterface
class WidgetInterface{
public:
// have to define this so we can call it while iterating
// (would remove from Widget if ended up using this SuperWidget
// non-template baseclass method)
virtual void method() = 0;
};
template <class TDataType>
class AbstractWidget : public WidgetInterface{
public:
TDataType mData;
virtual void method() = 0;
// ... bunch of helper methods etc
};
class EnumWidget : public AbstractWidget<SomeEnum>{
public:
EnumWidget(){
mData = HIGH;
}
void method(){
printf("%d\n", mData); // sprintf for simplicity
}
};
class IntWidget : public AbstractWidget<int>{
public:
IntWidget(){
mData = -1;
}
void method(){
printf("%d\n", mData); // sprintf for simplicity
}
};
int main(){
// this compiles but isn't a workable solution, not generic enough
std::vector< AbstractWidget<int>* > widgets1;
// only way to do store abitary subclasses?
std::vector<WidgetInterface*> widgets2;
widgets2.push_back(new EnumWidget());
widgets2.push_back(new IntWidget());
for(std::vector<WidgetInterface*>::iterator iter = widgets2.begin();
iter != widgets2.end(); iter++){
(*iter)->method();
}
// This is what i'd _like_ to do, without needing WidgetInterface
// std::vector< AbstractWidget* > widgets3;
return 0;
}
No, you can't use directly AbstractWidget as a parameter of STL container or anything else.
The reason is that class AbstractWidget does not exist. It is only a template for compiler to construct classes from.
What exists is AbstractWidget<SomeEnum> and AbstractWidget<int> only because of EnumWidget and IntWidget inheriting from them.
Templates exist at compiler-level only. If AbstractWidget<T> weren't used anywhere in your code, there would be no traces of it during the runtime.
Therefore, the code you posted seems to be the best (if not only) solution for your problem.
What you've done is the solution: you need a common class/interface, and since AbstractWidget is class template, therefore it cannot be used as common class for all concrete classes for which the template argument is different. So I think, you should go with this class design. It seems to be quite reasonable solution.
In fact the classes AbstractWidget<int> and AbstractWidget<double> are different classes, so your class IntWidget is a subclass of the first but is in no relation with the second. You need to have a common parent class to put in the vector so unfortunately you can not avoid the common interface that is not templated.
This could be completely in the wrong direction, but could you do something like this:
template <class T>
class ConcreteWidget : public AbstractWidget<T>
{
};
and then use template specialization to define your specific widgets like this:
template <>
class ConcreteWidget : public AbstractWidget<int>
{
public:
ConcreteWidget() : mData(-1) {}
};
template <>
class ConcreteWidget : public AbstractWidget<SomeEnum>
{
public:
ConcreteWidget() : mData(HIGH) {}
};
So rather than having an IntWidget and an EnumWidget, you'd have a ConcreteWidget and ConcreteWidget and then could simply have a vector<WidgetInterface> that would be the super of all of these generic children?
I'm not sure if this solves your problem, or would even work. I'd love feedback on this answer.

Storing multiple types of a templated class into a container

If I have a class with a template:
template<typename T>
class foo{
T m_a;
foo(T a){
m_a = a;
};
~foo(){
};
};
Is there a way to store multiple variation of it ?
For example a vector that can store a pointer to foo< int > and foo< string > at the same time ?
Edit more info
I want to hide the implementation of this :
EventListener<string> ev1;
EventListener<int, int> ev2;
EventListener<int, string, double> ev3;
ev1(&Events::nameChange, &nameChangeCallback);
ev2(&Events::healthChange, &healthChangeCallback);
ev3(&Events::newUser, &newUserCallback);
ev1.processEvents();
ev2.processEvents();
ev3.processEvents();
into this:
EventManager em;
em.listen(&Events::nameChange, &nameChangeCallback);
em.listen(&Events::healthChange, &healthChangeCallback);
em.listen(&Events::newUser, &newUserCallback);
em.processEvents();
EventManager needs to create and store EventListeners into a vector to be able to remember them and delete them in the destructor.
That's where I'm stuck.
If you want e.g. std::vector<foo<T>*>, then you need to use a non-templated base class. It will need to use dynamic dispatch, so all of the public interface should be declared virtual.
struct foo_base {
virtual ~foo_base() {}
virtual void something() = 0;
};
template <typename T>
struct foo : foo_base {
// ...
void something() { /* do something with T */ }
};
Then your container is std::vector<foo_base*>. Another, perhaps better, way, is to use boost::variant. This limits the number of types you can store, but at the same time doesn't require base class and virtual interface.
typedef boost::variant<foo<int>, foo<std::string>> foo_variants;
std::vector<foo_variants> v;
Third way is to use boost::any, but that will require boost::any_cast wherever you use them, and allow absolutely anything to be stored in the vector.
std::vector<boost::any> v;
Different instantiations of a class-template are different (from the compilers perspective completely unrelated) types, so this question applies.

Dedicating a field in arbitrary class types for "external use"

My container needs to store a little information about its elements. Normally, I store this separately from elements. However, I'd like to give users possibility to conserve memory by dedicating a field in element structure type for external use. E.g.:
struct MyStuff
{
int foo;
char bar;
mutable char dedicated_for_external_use; // Because of alignment, this field
// won't increase sizeof (MyStuff)
};
The idea here is that the field must not be accessed by anything but element's container. Since containers store a copy (much like std::vector), it wouldn't be a problem if you added any given value x to several containers.
How would you design an interface for this that, if possible, would meet the following requirements?
Should be completely optional. I.e. it should be possible to automatically determine if given type provides such a field or not and then container would only use it if available.
Ideally, wouldn't depend on type traits etc. as I need maximum compiler compatibility.
Should be easy to use. I.e. if you can and want to enable this optimization for type MyStuff, you could do it with 3 lines of code, not 25. Internal complications, on the other hand, don't matter.
Should preferably exclude false positives completely. What I mean is: if you check for field foo_bar there is a small posibility that such field exists for a completely unrelated reason (and I think duck-typing is simply not for C++). A better way would be to check if type inherits marker class ProvidesExternalUseField from my library, as this can't be by accident.
EDIT
I know about Boost.Intrusive, but what I want is something different. If I go that way and create a hooks class with a single char field, it cannot be used to conserve memory in many cases. If inherited type has an int as first field, char field will be padded to 4 bytes. I.e. you'd often need intricate knowledge of type internals to be able to "squeeze" such extern-use field in, but inheritance doesn't really provide it:
struct hooks { mutable char dedicated_for_external_use; };
struct MyStuff : hooks
{
int foo;
char bar;
};
Here, size of MyStuff will be 12 bytes, not 8.
You can use partial template specialization for the case your data struct derives from the marker interface.
Let's say your marker interface class looks like this:
class ProvidesExternalUseField
{
public:
char GetExtraField () { return 0; }
void SetExtraField (char newVal) {}
};
It is not virtual for a purpose: we wouldn't want to add a vtable pointer to a data class just for this.
Now let's implement a simple container class:
template <class T>
class Container
{
public:
char GetExtraValue ()
{
return 0; // here we cannot know if T is derived from the marker
}
private:
T m_t;
};
And here is how we change it to distinguish between the 2 cases:
template <class T, bool DoesTProvideExternalUseField>
class ContainerImpl
{
public:
char GetExtraValue () { return 0; }
private:
T m_t;
};
template <class T>
class ContainerImpl<T, true>
{
public:
char GetExtraValue () { return m_t.GetExtraField(); }
private:
T m_t;
};
template <class T>
class Container: public ContainerImpl<T,
boost::is_base_of<ProvidesExternalUseField,T>::value>
{
};
Now you can define the structs like this:
struct A
{
int m_intVal;
};
struct B: public ProvidesExternalUseField
{
char GetExtraField () { return m_extraField; }
void SetExtraField (char newVal) { m_extraField = newVal; }
int m_intVal;
char m_charVal;
char m_extraField;
};
And use the container class in the exact same way:
Container<A> a;
Container<B> b;
You can also further automate (templatize) getters and setters in the marker interface by using a poiter-to-member as a template parameter.