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.
Related
I have numerous objects implementing an interface called ExposesCommands.
class ExposesCommands
{
virtual bool get_command_results(std::string command, std::vector<std::string> &results) = 0;
};
typedef std::unique_ptr<ExposesCommands> ExposesCommands_ptr;
Commands are exposed via a template class:
template <typename T>
class ExposedCommands : public ExposesCommands
{
private:
static std::map<const char*, std::string T::*, cmp_str> exposed_cmds;
public:
virtual bool get_command_results(std::string command, std::vector<std::string> &results);
}
Now, I am trying to add sub-commands. Sub-commands will link to sub-objects that implement the commands. The way I would like to add them is like so:
template <typename T>
class ExposedCommands : public ExposesCommands
{
private:
static std::map<const char*, std::string T::*, cmp_str> exposed_cmds;
static std::map<const char*, std::vector<ExposesCommands_ptr> T::*, cmp_str> exposed_sub_cmds;
public:
virtual bool get_command_results(std::string command, std::vector<std::string> &results) {
auto &it = exposed_cmds.find(command.c_str());
if (it != exposed_cmds.cend()) {
auto x = std::bind(it->second, std::placeholders::_1);
std::string data = x(*((T*)this));
if (data != "") {
results.push_back(data);
}
return true;
}
// else check if in exposed_sub_cmds.
// if so, iterate through vector, call get_command_results
// on remainder of command name for each sub object, adding
// its result to the vector of results.
// return true
//
return false;
}
}
I have objects like this implementing the interface (building of the maps is not shown here):
class ObjectA : public ExposesCommands<ObjectA>
{
public:
std::string cmd_x; // command X
std::string cmd_y; // command Y
}
typedef std::unique_ptr<ObjectA> ObjectA_ptr;
class ObjectB
{
public:
std::string cmd_z; // command Z
std::vector<ObjectA_ptr> my_as; // 'ObjectA' sub commands
}
Unfortunately, this doesn't work because I can't assign a &std::vector<ObjectA_ptr> to a std::vector<ExposesCommands_ptr> T::*.
Is there any way to get around this? Or a better approach to this problem?
To summarize your problem: You have a base class and some derived classes
class Base {
public:
virtual ~Base();
};
class Derived1 : public Base;
class Derived2 : public Base;
You need to store a collection of pointers (for ownership management you chose to use std::unique_ptr, which seems wise) to Derived1 objects in a way that it can be used by code that doesn't know Derived1 exists, and only wants to use properties of Base, but also do not want to lose the property that this specific collection of Base objects actually contains Derived1 objects only. This is a kind of type erasure, as the runtime behaciour of the collection should not depend on whether it stores Base, Derived1 or Derived2 objects (or even a mixture of it, so that property gets erased), yet at compile time, you don't want to write all those ugly downcasts (and you want the compiler to verify you only downcast objects from a container you statically know that it does only contain Derived1 objects). Be aware that if you are going to store pointers to Derived1 in std::unique_ptr<Base>, it is absolutely necessary that Base has a virtual destructor.
I don't know any ready-made solution for this off-hand (it couldn't find something skimming over the Boost libraries tagged Container, too), but I can show you how reach that goal yourself. You need a template, to get different compile-time types (just as std::vector is a template), which internally stores the data in a fixed type. So something like this:
typedef std::unique_ptr<Base> Base_ptr;
template <typename T>
class BaseVector {
public:
const std::vector<Base_ptr> &
as_baseclass_vector() const
{
return backing_;
}
private:
std::vector<Base_ptr> backing_;
};
Note that as_baseclass_vector does return a const reference to the raw vector, because the result must not be used to insert objects of the wrong type (e.g. pointers to Derived2 objects) into a CommandVector instantiated for Derived1. This is only half the way to go, the other half is sadly reimplementing the standard library container concept on this vector-wrapper, along this:
template<typename T>
void CommandVector::push_back(std::unique_ptr<T> obj)
{
backing_.push_back(std::move(obj));
}
or, more importantly and interestingly:
template<typename T>
const T* BaseVector::operator[](size_t index) const
{
return static_cast<T*>(backing_[index]);
}
Note that this operator[] does not return a reference-to-unique_ptr, as it could only return a reference to a unique_ptr<Base>, because that is what is stored in the backing vector. If it created a tempory unique_ptr to T, it would have to remove the ownership from the vector - you definitely would not want that! The result has been declared const, because it returns a copy instead of the usual reference, and modifying the return value (which is now forbidden) does not modify the object in the vector, opposed to what users expect. You would have to reimplement all the other methods (iterators would get quite interesting, but probably can be based on boost::transform_iterator) yourself if you chose to go this route.
What is the most elegant way to provide an interface in C++ that accepts derived class types that carry with them different data type members that then need to be retrieved later. The example below illustrates this where the Container class provides methods to "post" an Item that will be some kind of derived variant of BaseItem. Later on I want to get the derived Item back and extract its value.
The main thing I want is for the Container interface (post and receive) to stay the same in the future while allowing different "Item" derived types to be defined and "passed" through it. Would template be better for this somehow; I'd rather not use RTTI. Maybe there is some simple, elegant answer to this, but right now I'm struggling to think of it.
class ItemBase {
// common methods
};
class ItemInt : public ItemBase
{
private:
int dat;
public:
int get() { return dat; }
};
class ItemDouble : public ItemBase
{
private:
double dat;
public:
double get() { return dat; }
};
class Container {
public:
void post(int postHandle, ItemBase *e);
ItemBase* receive(int handle); // Returns the associated Item
};
int main()
{
ItemInt *ii = new IntItem(5);
Container c;
c.post(1, ii);
ItemInt *jj = c.receive(1);
int val = jj->get(); // want the value 5 out of the IntItem
}
This is definitely a candidate for generic programming, rather than inheritance. Remember, generics (templates) are ideal when you want identical handling for different data types. Your ItemInt and ItemDouble classes violate OO design principles (the get() method returns different data types depending on what the actual subtype is). Generic programming is built for that. The only other answer would be a tagged data type, and I personally avoid those like the plague.
How about?
template<typename T>
class Item
{
private:
T dat;
public:
T get() { return dat; }
};
class Container {
public:
template<typename T>
void post(int postHandle, Item<T> *e);
template<typename T>
Item<T>* receive(int handle); // Returns the associated Item
};
int main()
{
Item<int> *ii = new Item<int>(5);
Container c;
c.post(1, ii);
Item<int> *jj = c.receive<int>(1);
int val = jj->get(); // want the value 5 out of the IntItem
}
Your Container class looks suspiciously like a std::map. It looks to me like your ItemBase class is just a different name for "Object", the universal base class, which I think is not much different from (or better than) void*. I would avoid trying to contain items of different type in a single container. If your design seems to call for doing so, I'd rethink your design.
A pure template approach doesn't work because you apparently want to have mixed types in your container. You could work with something like Boost's any although I think you need to restore the actual. What I think is called for in this case is a base class exposing the type-independent and virtual methods plus a templatized derived class to hold the actual items:
class Base {
public:
virtual ~Base() {}
virtual void post() = 0;
};
template <typename T>
class Item: public Base {
public:
Item(T const& value): value_(value) {}
void post() { std::cout << "posting " << this->value_ << "\n"; }
private:
T value_;
};
This approach avoids the need to write any derived Item class for another value type. To make creation of these beast easier you probably want to create a suitable creation function as well, e.g.
template <typename T>
std::unique_ptr<Base> make_item(T const& value) {
return std::unique_ptr<Base>(new Item<T>(value));
}
A std::unique_ptr<Base> is returned to make sure that the allocated object is released (if you don't use C++2011 you can used std::auto_ptr<T> instead). This type can easily be converted to other pointer types, e.g. to a std::shared_ptr<Base> which is a better suited to be put 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.
What are the ways in C++ to handle a class that has ownership of an instance of another class, where that instance could potentially be of a number of classes all of which inherit from a common class?
Example:
class Item { //the common ancestor, which is never used directly
public:
int size;
}
class ItemWidget: public Item { //possible class 1
public:
int height;
int width;
}
class ItemText: public Item { //possible class 2
std::string text;
}
Let's say there is also a class Container, each of which contains a single Item, and the only time anyone is ever interested in an Item is when they are getting it out of the Container. Let's also say Items are only created at the same time the Container is created, for the purpose of putting them in the Container.
What are the different ways to structure this? We could make a pointer in Container for the contained Item, and then pass arguments to the constructor of Container for what sort of Item to call new on, and this will stick the Items all in the heap. Is there a way to store the Item in the stack with the Container, and would this have any advantages?
Does it make a difference if the Container and Items are immutable, and we know everything about them at the moment of creation, and will never change them?
A correct solution looks like:
class Container {
public:
/* ctor, accessors */
private:
std::unique_ptr<Item> item;
};
If you have an old compiler, you can use std::auto_ptr instead.
The smart pointer ensures strict ownership of the item by the container. (You could as well make it a plain pointer and roll up your own destructor/assignment op/copy ctor/move ctor/ move assignment op/ etc, but unique_ptr has it all already done, so...)
Why do you need to use a pointer here, not just a plain composition?
Because if you compose, then you must know the exact class which is going to be composed. You can't introduce polymorphism. Also the size of all Container objects must be the same, and the size of Item's derived classes may vary.
And if you desperately need to compose?
Then you need as many variants of Container as there are the items stored, since every such Container will be of different size, so it's a different class. Your best shot is:
struct IContainer {
virtual Item& getItem() = 0;
};
template<typename ItemType>
struct Container : IContainer {
virtual Item& getItem() {
return m_item;
}
private:
ItemType m_item;
};
OK, crazy idea. Don't use this:
class AutoContainer
{
char buf[CRAZY_VALUE];
Base * p;
public:
template <typename T> AutoContainer(const T & x)
: p(::new (buf) T(x))
{
static_assert(std::is_base_of<Base, T>::value, "Invalid use of AutoContainer");
static_assert(sizeof(T) <= CRAZY_VAL, "Not enough memory for derived class.");
#ifdef __GNUC__
static_assert(__has_virtual_destructor(Base), "Base must have virtual destructor!");
#endif
}
~AutoContainer() { p->~Base(); }
Base & get() { return *p; }
const Base & get() const { return *p; }
};
The container requires no dynamic allocation itself, you must only ensure that CRAZY_VALUE is big enough to hold any derived class.
the example code below compiles and shows how to do something similar to what you want to do. this is what in java would be called interfaces. see that you need at least some similarity in the classes (a common function name in this case). The virtual keyword means that all subclasses need to implement this function and whenever that function is called the function of the real class is actually called.
whether the classes are const or not doesn't harm here. but in general you should be as const correct as possible. because the compiler can generate better code if it knows what will not be changed.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class outputter {
public:
virtual void print() = 0;
};
class foo : public outputter {
public:
virtual void print() { std::cout << "foo\n"; }
};
class bar : public outputter {
public:
virtual void print() { std::cout << "bar\n"; }
};
int main(){
std::vector<outputter *> vec;
foo *f = new foo;
vec.push_back(f);
bar *b = new bar ;
vec.push_back(b);
for ( std::vector<outputter *>::iterator i =
vec.begin(); i != vec.end(); ++i )
{
(*i)->print();
}
return 0;
}
Output:
foo
bar
Hold a pointer (preferably a smart one) in the container class, and call a pure virtual clone() member function on the Item class that is implemented by the derived classes when you need to copy. You can do this in a completely generic way, thus:
class Item {
// ...
private:
virtual Item* clone() const = 0;
friend Container; // Or make clone() public.
};
template <class I>
class ItemCloneMixin : public Item {
private:
I* clone() const { return new I(static_cast<const I&>(*this); }
};
class ItemWidget : public ItemCloneMixin<ItemWidget> { /* ... */ };
class ItemText : public ItemCloneMixin<ItemText> { /* ... */ };
Regarding stack storage, you can use an overloaded new that calls alloca(), but do so at your peril. It will only work if the compiler inlines your special new operator, which you can't force it to do (except with non-portable compiler pragmas). My advice is that it just isn't worth the aggravation; runtime polymorphism belongs on the heap.
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.