I have multiple controls organized like this:
deque<wxTextCtrl*> dequeEdit;
deque<wxStaticText*> dequeText;
deque<wxComboBox*> dequeCombo;
All these controls inherit from wxWindow which has mathod Show. I'd like to show (or hide) whole deque at once, without the need of multiple methods for each deque. How could it be done?
I was thinking about making deque of wxWindow for each control, so I could write method
ShowDeque(deque<wxWindow*> deque)
so showing would be easy, but on the other hand, if I'd like to work with e.g. combobox, I'd have to type it back to wxComboBox.
Are there any other possibilites? Thanks.
Use:
for_each(dequeEdit.begin(), dequeEdit.end(), mem_fun(&wxWindow::Show));
Same for any other deques.
Or encapsulate in one function:
template <class Deque>
void showAll(const Deque& dequeObj)
{
using namespace std;
for_each(dequeObj.begin(), dequeObj.end(), mem_fun(&wxWindow::Show));
}
showAll(dequeEdit);
std::for_each: http://en.cppreference.com/w/cpp/algorithm/for_each
std::mem_fun: http://en.cppreference.com/w/cpp/utility/functional/mem_fn
If it's a simple method make it a template:
template <typename WxT>
void ShowDeque(std::deque<WxT*> &d) { ... }
or better, use iterators to abstract out the container type:
template <typename WxIter>
void ShowDeque(WxIter begin, WxIter end) { ... }
or better yet use the standard facilities (Piotr beat me to that one while I was typing!)
You can use a function template.
template <typename T>
void show_all(const std::deque<T*>& d) {
for (typename std::deque<T*>::iterator it=d.begin(); it!=d.end(); ++it)
(*it)->Show();
}
You can then call it like a normal function.
deque<wxTextCtrl*> dequeEdit;
deque<wxStaticText*> dequeText;
deque<wxComboBox*> dequeCombo;
show_all(dequeEdit);
show_all(dequeText);
show_all(dequeCombo);
With a function template you can even make show_all independent of the container you use by adding an additional template argument.
template <typename C, typename T>
void show_all(const C<T*>& d) {
for (typename C<T*>::iterator it=d.begin(); it!=d.end(); ++it)
(*it)->Show();
}
C can then be any STL container, or even any container which supports the same iterator interface.
I came across this question when looking for how to use inheritance of iterators and deque.
The answer's does not give a complete answer related to inheritance, so I will add following:
Let say you have a class and you want this class to have the ability to have a deque inside, in other words to inherit the ability to control a deque container.
Example :
template<typename ElementType>
class myQueOfElements : public deque<ElementType>
{
ElementType placeholder;
myQueOfElements& operator=(unsigned char* rvalue)
{
unsigned char* ptrToNextElement = (unsigned char*)rvalue;
placeholder = ptrToNextElement; // make sure ElementType has its own assignment operator=
push_back(placeholder); // First element
//TODO: Iterate thru the binary and push_back the fetched elements
return *this;
}
};
// How to use:
myQueOfElements<myElementTypeClass> testQue;
testQue = (unsigned char*)&blob[0]; // address to binary data, will be parsed in the assignment operator=
// make sure it has same structure as the ElementType (myElementTypeClass)
// fetch all myElementTypeClass object(s) from the myQueOfElements
for (auto e : testQue) {
std::string strName = e.Name;
std::out << "Element : " << strName.c_str() << endl;
}
Related
I have a class which acts on a list of elements, like so:
template <typename T>
class MyClass {
...
};
I need to implement certain methods, that work both on a vector<T> and a string - which is what most of the users would be using when they initialise an object as MyClass<char>().
Due to this I am being forced to follow this overloading pattern:
void method(vector<T> elements){
}
void method(string elements){
method(convertStringToVector(elements));
}
where vector<char> convertStringToVector(string str) is defined as expected.
That is, for each class method I am being forced to add an additional method that overloads for string. I find it an unnecessary overhead, and also sometimes forget to add it.
I will be doing exactly the same things on the string as I would do on the corresponding vector - same methods will be called in both cases, same iteration, etc. Thus, I was wondering if there is a cleaner way to do this, without adding much code overhead. Is there?
One possible way is to implement your method as a template, whose parameter is not restricted to be either string or vector<char>.
template <typename T>
struct MyClass
{
template <class C>
void method(C container);
};
This solves your problem because one implementation is enough for both cases:
template <typename T>
template <class C>
void MyClass<T>::method(C container)
{
std::cout << "Container has size " << container.size() << '\n';
std::cout << "First element is " << container[0] << '\n';
}
However, this will work on any container. It's not clear whether this is good (code is generic) or bad (code allows undesirable instantiations).
Imagine what happens when people try to send vector<int> instead of vector<char> to your method by mistake. Because you didn't build your code for this case, it will either display obscure compilation errors, or generate code which silently does the wrong thing at runtime.
You can create a class to use as parameter to your methods, which accepts both std::vector<char> and std::string:
class MyString
{
public:
MyString(const std::vector<char>& v) : vector(v) {}
MyString(std::vector<char>&& v) : vector(std::move(v)) {}
MyString(const std::string& s) : vector(convertStringToVector(s)) {}
std::vector<char> vector;
};
void method(MyString elements)
{
}
You can define convertStringToVector as method of your class like this:
vector<T> convertStringToVector(string str)
or a separate template function, if you need it independently for other classes.
Also I would pass the argument as reference const string &str.
If any template parameter you use is incompatible with the algorithm, the compiler will tell you about.
For those special cases you can still write a template specialization like this:
template<>
vector<SPECIALTYPE> convertStringToVector<SPECIALTYPE>(string str)
{
...
}
and implement different code for such SPECIALTYPE.
I have a class called DBDriver that handles communication with a given table in a database. Its public entry point is a function template called execute_query(), which executes SELECT queries. Upon calling this function, some database logic is performed, and then a provided container (of the template type) is populated with results. This looks something like the following:
class DBDriver {
...
template <typename CONT_T>
void execute_query(const std::string& query, CONT_T& container);
...
};
template <typename CONT_T>
void DBDriver::execute_query(const std::string& query, CONT_T& container) {
DBCursor& cursor = ... // some database logic here
populate_container(container, cursor);
}
Of course, the above will not compile, as populate_container() is not defined in DBDriver.
DBDriver should be purely virtual and have several classes derive from it (one for each database table involved). Each derived class will define its own overloads of populate_container(), one for each relevant container type. This will look something like the following:
class SampleTableDBDriver : public DBDriver {
// ...
populate_container(const ContainerTypeOne& container, DBCursor& cursor);
populate_container(const ContainerTypeTwo& container, DBCursor& cursor);
// ...
};
My original attempt at this was unsuccessful, as I would have needed to define a virtual function template in DBDriver to serve as an entry point to a derived class' populate_container() overloads. (Of course such a thing does not exist in C++, hence my issue.)
Is there a cleaner, idiomatic solution for this type of problem?
The reason why execute_query is a template function is you need a generic container. What if you define a Interface for the container?
class IContainer
{};
Template Functions cannot be virtual. Therefore, you can use the Template Method Design Pattern.
class DBDriver
{
public:
void execute_query(const std::string& query, IContainer **_ppContainer);
{
DBCursor& cursor = ... // some database logic here
populate_container(_ppContainer, cursor);
}
virtual void populate_container(IContainer **_ppContainer, DBCursor &_dbCursor) = 0;
};
And let every derived class implement populate_container and also provide their custom Container.
class SampleTableDBDriver : public DBDriver
{
public:
class ContainerTypeOne : public IContainer
{};
void populate_container(IContainer **_ppContainer, DBCursor &_dbCursor)
{
ContainerTypeOne *pContainer = new ContainerTypeOne();
//....
(*_ppContainer) = pContainer;
}
};
SampleTableDBDriver oSampleDriver;
IContainer *pContainer = NULL;
std::string szQuery = // some query ;
oSampleDriver.execute_query(szQuery, &pContainer);
if(pContainer != NULL)
{
SampleTableDBDriver::ContainerTypeOne *pSampleDriverContainer =
dynamic_cast<SampleTableDBDriver::ContainerTypeOne*>(pContainer);
//use pSampleDriverContainer
}
Edit: For supporting multiple containers.
In your original design the populate_container seems to be overloaded in derived classes. In that case you would still pass the exact container from outside while calling execute_query.
Same thing can be done with this Template Method design. Then, you will need to decipher the type of container inside the populate_container function as follows:
New signature : int populate_container(IContainer *_pContainer, DBCursor &_dbCursor)
int populate_container(IContainer *_pContainer, DBCursor &_dbCursor)
{
if(dynamic_cast<ContainerTypeOne *>(_pContainer) != NULL)
{
ContainerTypeOne *pContainerOne = _pContainer;
//populate the result by using pContainerOne
return 1;
}
if(dynamic_cast<ContainerTypeTwo *>(_pContainer) != NULL)
{
ContainerTypeOne *pContainerTwo = _pContainer;
//populate the result by using pContainerTwo
return 1;
}
//no, I do not support the container you passed.
return 0;
}
SampleTableDBDriver oSampleDriver;
SampleTableDBDriver::ContainerTypeOne oSampleContainerTypeOne;
std::string szQuery = // some query ;
if(oSampleDriver.execute_query(szQuery, &oSampleContainerTypeOne) != 0)
{
//use oSampleContainerTypeOne;
}
You have options to choose from:
If you don't need populate_container() to be a member of DBDriver and can extend (or define) container interface, just implement
ContainerTypeOne::populate(DBCursor& cursor);
Make populate_container() a friend (in case you need access to private members of DBDriver):
template <typename CONT_T> friend void execute_query(const std::string& query, CONT_T& container);
Make populate_container() a non-member template function (if you don't need access to private members of DBDriver)
One way to do this is to employ the separation of concerns principle.
Querying databases goes to its own class hierarchy, and populating container goes to its own separate class hierarchy. These two hierarchies know nothing about each other, e.g. DBDriverThirteen knows nothing about ContainerFortyTwo. The two hierarchies only touch at their roots, i.e. DBDriver (and so its every derived class) knows about IContainerPopulator but nothing about any specific containers.
You may have a template that builds a specific ContainerPopulator for each container type. Assume for simplicity that you only need to support standard containers of strings that implement push_back.
struct IContainerPopulator {
virtual void push_back(const std::string&) = 0;
};
template <class CONT_T>
struct ContainerPopulator : IContainerPopulator {
StandardContainerPopulator (CONT_T& cont) : cont(cont) {}
void push_back(const std::string& s) override { cont.push_back(s); }
private:
CONT_T& cont;
};
Now you can do this
template <typename CONT_T>
void execute_query(const std::string& query, CONT_T& container) {
execute_query_adapted(query, ContainerPopulator<CONT_T>(container));
}
// no template!
virtual void execute_query_adapted(const std::string&,
IContainerPopulator&&) = 0;
By now you have probably recognised that IContainerPopulator is nothing but a specialised poor man's function binder. Why write another one if we have pretty good support in the language and its standard library? If you only need to support push_back, you can alternatively do this:
template <typename CONT_T>
void execute_query(const std::string& query, CONT_T& container) {
execute_query_adapted2(query,
[&](const std::string& s){container.push_back(s);});
}
// no template
virtual void execute_query_adapted2(const std::string&,
std::function<void(const std::string&)>) = 0;
Now if you need more than just push_back (or any fixed set of functions) and/or more than std::string (or any fixed set of types), things can get really hairy. More information would be needed about potential implementations of populate_query.
As long as you don't mind using RTTI (or Boost.TypeIndex, which doesn't require RTTI), you can use type erasure and void* to get what you want. It's a bit dirty, but it does the job.
#include <functional>
#include <typeindex>
#include <unordered_map>
class driver {
public:
template <typename Container, typename Populator>
void register_populator(Populator populator) {
populators[type_index<Container>()] = [populator](void* v) {
Container& container = *static_cast<Container*>(v);
populator(container);
};
}
template <typename Container>
void execute(Container& container) {
auto it = populators.find(type_index<Container>());
if (it != populators.end()) {
it->second(&container);
}
}
private:
template <typename T>
static std::type_index type_index() {
return std::type_index(typeid(std::remove_cv_t<T>));
}
std::unordered_map<std::type_index, std::function<void (void*)>> populators;
};
Then use like so:
#include <vector>
#include <iostream>
int main() {
driver d;
d.register_populator<std::vector<int>>([](std::vector<int>&) {
std::cout << "Populate vector<int>\n";
});
d.register_populator<std::vector<float>>([](std::vector<float>&) {
std::cout << "Populate vector<float>\n";
});
std::vector<int> int_vector;
std::vector<float> float_vector;
d.execute(int_vector);
d.execute(float_vector);
}
Output:
Populate vector<int>
Populate vector<float>
I have legacy code where a similar method is used to cycle through a sequential container (vector in this example. Some implementations use other kinds of containers). So I factored it out into a template so I could reuse the same piece of code for any container type.
template<template<class, class> class TContainer, class TObject>
class cycle
{
public:
explicit cycle( TContainer<TObject, std::allocator<TObject>> & container )
: mContainer( container ), index(0) {}
TObject getNext(int numObjectsToCycle)
{ return mContainer[index++ % numObjectsToCycle]; }
private:
TContainer<TObject, std::allocator<TObject>> & mContainer;
int index;
};
Then my class has a cycler to cycle through my variable numbers.
class myClass
{
std::vector<int> numbers;
public:
cycle<vector, int> cycler;
// Is it safe to pass numbers since it is declared first??
myClass() : cycler(numbers) {}
};
Then, I use the code like below.:
myObject.cycler.getNext(size);
Is it a good programming practice to pass the vector "numbers" to cycler? Is there a better way of implementing my template?
The code really is to be able to infinitely loop through objects. My class is invoked from external code that just calls a member method, and I want to be able to just call getNext() so I wouldn't have to use an index.
In the standard library another "pattern" exists and it's the iterator pattern. Basically every container type implements begin and end which returns, respectively, the iterator to the first element and the past-the-end element (which is always guaranteed to exists).
This works for every container type, from std::vector to std::array including C-style arrays with std::begin and std::end. If you want to loop in a generic container you can do, for example:
template<typename Container>
void cicle(Container const& c) {
for (auto const& i : c) {
// …
}
}
or, to better visualize the pattern:
template<typename Container>
void cicle(Container const& c) {
for (auto it = std::begin(c); it != std::end(c); ++it) {
// …
}
}
Live demo
I have a class which has a template:
template<class T = int> class slider;
The class has a void Process(void) method, so, I think it should be callable regarless of the type, return value is void and there are no parameters to it.
As for now I have this code to call process each frame in my application:
//class menu:
typedef boost::variant<std::shared_ptr<slider<int>>,std::shared_ptr<slider<float>>,std::shared_ptr<slider<double>>,std::shared_ptr<slider<char>>> slider_type;
std::map<std::string,slider_type> Sliders;
//buttons ... etc ...
void Process()
{
if(!Sliders.empty())
{
for(auto i = Sliders.begin(); i != Sliders.end(); ++i)
{
switch(i->second.which())
{
case 0://slider<int>
{
boost::get<std::shared_ptr<slider<int>>>(i->second)->Process();
break;
}
case 1://slider<float>
{
boost::get<std::shared_ptr<slider<float>>>(i->second)->Process();
break;
}
//.....
}
}
}
}
Is it possible to execute the functions Process() like in the following example?
for(auto i = Sliders.begin(); i != Sliders.end(); ++i)
{
switch(i->second.which())
{
boost::get<???Any???>(i->second)->Process();
}
}
If yes, how?
What would such a function return? You can't change the type of a function at runtime. And the point of a variant is that it's contents are determined at runtime.
The only thing it could return is a boost::any. Which is really just exchanging one kind of unknown for another (an unknown that's a lot harder to deal with when you don't know what it contains, mind you). But if you want to see such a visitor:
struct convert_to_any : public boost::static_visitor<boost::any>
{
template<typename T> boost::any operator() (const T& t) {return t;}
};
Use apply_visitor on that, and you will get an any back. Though I fail to see how that's helpful.
In any case, if you're using get on a variant, you are almost certainly doing the wrong thing. The correct way to access the elements of a variant is with a visitor, not with get.
In your case, the visitor should be simple:
struct ProcessVisitor : public boost::static_visitor<>
{
template<typename T> void operator() (const T& t) const {t->Process();}
};
Just use apply_visitor on that. If the variant contains a type that can be used with operator-> and the return value of that function can have Process called on it, then it will.
(Untested code!)
struct CallProcess : static_visitor<>
{
template <class T>
void operator()(const T &t) const
{
t->Process();
}
};
for(auto i = Sliders.begin(); i != Sliders.end(); ++i)
{
boost::apply_visitor(CallProcess(), i->second);
}
No, not at all. You have to visit and deal with the case of every type. That is much better done with a visitor than your switch hack.
It's not possible because boost::variant has no way to know that all the types in the variant have anything in common. In fact, since the compiler generates a distinct class for each template specialization used, the address of the Process() function that would need to be used is different for each type in the boost::variant. To get around this you could abandon variant and use virtual functions and polymorphic classes sharing a common base class.
I am trying to write wrapper classes around std::list and std::vector with their own iterators so that I can then write a superclass for both of those classes and their iterators. My current code looks basically like this:
template <class T>
class MyCollection
{
//Not sure how to write this class.
public:
class iterator
{
//Not sure how to write this class either
//I think MyVector::iterator and MyList::iterator
//should inherit from this class
};
};
template<class T>
class MyVector : public MyCollection<T>
{
private:
vector<T> data;
public:
MyVector(int * start, int * end) : data(start, end) {}
class iterator : vector<T>::iterator
{
iterator(typename vector<T>::iterator i) : vector<T>::iterator(i) {}
};
iterator begin() { return iterator(data.begin()); }
};
template<class T>
class MyList : public MyCollection<T>
{
private:
list<T> data;
public:
Mylist(int * start, int * end) : data(start, end) {}
class iterator : list<T>::iterator
{
iterator(typename list<T>::iterator i) : list<T>::iterator(i) {}
};
iterator begin() { return iterator(data.begin()); }
};
I would like to be able to have some code that does this:
int ints[] = {1,2,3,4,5};
MyList<int> l(ints, ints+5);
MyCollection<int> * c = &l;
MyCollection<int>::iterator i = c->begin();
and after that code executes, I would like to be able to iterate through the MyList l using i.
I feel like there needs to be a virtual begin() member function in MyCollection, but I cannot figure out what the proper return type should be.
Is what I'm trying to do even possible? It's entirely possible that the current organization of my code is totally wrong. That's just what I've tried. My goal is just to get it so that the example driver code above can work, so an answer may involve a total restructuring of the code. I'm really just looking for suggestions. I don't need a complete answer.
I wouldn't write a wrapper for std::vector and std::list in this case for the sole purpose of using std::list or std::vector uniformly. You don't need to.
What you want is to use type erasure in a similar way to what you can find here.
The whole idea for you would be to implement only MyCollection<T> with a type erased iterator and use type erased iterator for traversing any of the collections. No need for MyList<T> or MyVector<T>.
MyCollection::begin should return a MyCollection::iterator, by convention. Therefore MyVector::begin() should return something that's at least a MyCollection::iterator, too. It may be a more derived type, though.
In your case, MyVector::begin() returns a MyVector::iterator, which is not derived from MyCollection::iterator. That's why it fails.