I sorry if similar question already exists on this forum, if you could, give me the link.
I have a template class
template<typename type>
class DoublyLinkedList {};
And I want to have Sort method in it.
template<typename type>
class DoublyLinkedList
{
public:
void Sort(){}
};
But list is template so it can contains different types. So how I can create methods for all types that I foresee? I tried in this way:
template<typename type>
class DoublyLinkedList
{
public:
void DoublyLinkedList<int>::Sort(){}
void DoublyLinkedList<string>::Sort(){}
};
But it's wrong. Please help.
The way the standard library generally deals with this problem is to allow users to specify their own compare functions. You can add a templated parameter that users of your type can use to provide a Compare function, like std::sort does. In the implementation of sort, you assume that comparer is a function that compares two elements of the list and returns rather or not the first should be before the second.
#include <string>
template<typename type>
class DoublyLinkedList
{
public:
template<class Comp>
void Sort(Comp comparer);
};
void foo(DoublyLinkedList<std::string> & list)
{
// Sort list by length of strings
list.Sort([](const std::string p_left, const std::string p_right){
return p_left.size() < p_right.size();
});
}
Related
I'm trying to understand how templates work, and I've come up with this problem. Now, I'm perfectly aware that it can be solved using polymorphism, but I'm curious to see if it can be solved by just using templates. The situation is as follows:
Suppose I have two types of queues, which are defined as follows:
#include <queue>
template <typename GenType, typename Comparator>
class Priority
{
public:
Priority()
{ }
~Priority()
{ }
void insert(GenType const& t)
{ mQueue.push(t); }
private:
std::priority_queue<GenType, std::vector<GenType>, Comparator> mQueue;
};
template<typename GenType>
class FIFO
{
public:
FIFO()
{ }
~FIFO()
{ }
void insert(GenType const& t)
{ mList.push_front(t); }
private:
std::deque<GenType> mList;
};
And now, I have a class that can use either Queue or FIFO (or any other type of queue) as shown here:
// I'm not sure that this is how it should be declared...
template <typename GenType,
template<typename, typename...> class List>
class User
{
public:
User()
{ }
~User()
{ }
void add(GenType const& t)
{ mList.insert(t); }
private:
// This line gives an error.
List mList;
};
As it stands, the marked line gives an error, which I understand since I haven't actually passed any template parameters to List. The thing is that I don't know how to solve this error.
To give some context, the use case for this was to be able to have the User class take a any type of queue and could be used like this:
User<int, FIFO> u1;
// Not sure if it is this way:
User<int, Priority, std::less<int>> u2;
// Or this way:
User<int, Priority, std::less> u2;
Any suggestions on how to solve this problem?
Don't do it that way.
Instead, let your User class template take the full type of the container it's going to use, and let the container indicate what type of values it takes:
template <typename Container>
class User
{
public:
using value_type = typename Container::value_type; // you'll have to add this
// typedef to your containers
User() = default;
~User() = default;
void add(value_type const& t)
{
mList.insert(t);
}
private:
Container mList;
};
This way, I, as the user of your class template, can provide the right thing. If I want to use your priority queue, I can pass in the comparator I want directly:
User<Priority<int, std::less<>>> u;
Or not:
User<FIFO<int>> u2;
Or maybe I wrote my own container which isn't even a class template:
User<SpecialContainer> u3;
Yours works either way. Generic is good.
There is already an accepted answer, but I'd like to show the desired syntax.
private:
// This line doesn't give an error.
List<GenType> mList;
};
Now this line compiles too:
User<int, FIFO> u1;
The last two lines can't be compiled because the template User accepts only two parameters. Just add a third parameter.
unfortunately my actual template is too full of stuff that is unrelated to my question, so i tried to put everything in a short example. Lets say, I have written the following template:
#include <vector>
template <typename T> class MyTemplate{
public:
typedef void(*MyFunc)(T);
void addFunc(MyFunc f){myFuncs.push_back(f);}
void callFuncs(T value){
for (std::size_t i=0;i<myFuncs.size();i++){myFuncs[i](value);}
}
private:
std::vector<MyFunc> myFuncs;
};
I learned already, that I can specialize this template to behave different when the passed type is a vector, so I wrote this:
template <typename T> class MyTemplate<std::vector<T> > {
public:
typedef void(*MySingleElementFunc)(T);
void addSingleElementFunc(MySingleElementFunc f){
this->mySingleElementFuncs.push_back(f);
}
void callFuncs(std::vector<T> value){
//for (std::size_t i=0;i<myFuncs.size();i++){
// myFuncs[i](value);
//}
for (std::size_t i=0;i<mySingleElementFuncs.size();i++){
for (int size_t i=0;i<value.size();i++){
mySingleElemetnFuncs[i](value[i]);
}
}
}
private:
std::vector<MySingleElementFunc> mySingleElementFuncs;
};
Now my question is, what is the most elegant way (if possible without inheritance) not only to specialize the template for the case of vector< T > but at the same time still being able to use the first templates methods where vector< T > is the template parameter. What I would like to do later is the following
void Func1(int i){}
void Func2(std::vector<int> i){}
MyTemplate<std::vector<int> > myTemplate;
myTemplate.addFunc(Func1);
myTemplate.addFunc(Func2);
Is it possible to achieve this without simply copy&paste all stuff I need from the original template, to do the same also with the specialized version? I guess I will have to use some kind of inheritance. However, I want to avoid something like this:
MyTemplate<std::vector<int> > myTemplate;
// myTemplate.addFunc(Func1); // does not work
myTemplate.addFunc(Func2);
MyVectorTemplate<std::vector<int> > myVectorTemplate;
myVectorTemplate.addFunc(Func1); // works
myVectorTemplate.addFunc(Func2);
i.e. the functionality should be determined only by the type passed to the template but not by choosing the appropriate subclass. Anyhow, I have to admit that I am a bit confused about how to inherit in this case. If it was not a template, I could write something like
class MyVectorClass : public MySingleObjectClass {}
However, the following does not make any sense:
template <typename T> MyTemplate<std::vector<T> > : public MyTemplate<std::vector<T> >
but in some sense, this is what I would like to have.
I am sorry for such a long post and I hope it is more or less clear what is my problem...
EDIT: I just found a mistake in the above code. The loop in the vector template should read
for (std::size_t i=0;i<mySingleElementFuncs.size();i++){
for (int size_t j=0;j<value.size();j++){
mySingleElemetnFuncs[i](value[j]);
}
}
i.e. each registered function should be called once for each entry in the vector. (Otherwise the template does not work if the number of registered functions is not equal to the size of the vector.)
In fact you want add functionality to the specialization, something like:
template <typename T> class MyTemplate<std::vector<T> >
{
public:
typedef void(*MySingleElementFunc)(T);
typedef void(*MyVectorFunc)(std::vector<T>);
void addSingleElementFunc(MyVectorFuncf){
this->myVcetorFuncs.push_back(f);
}
void addSingleElementFunc(MySingleElementFunc f){
this->mySingleElementFuncs.push_back(f);
}
void callFuncs(const std::vector<T>& value){
for (std::size_t i=0;i<myVectorFuncs.size();i++){
myVectorFuncs[i](value);
}
for (std::size_t i=0;i<mySingleElementFuncs.size();i++){
for (int size_t i=0;i<value.size();i++){
mySingleElemetnFuncs[i](value[i]);
}
}
}
private:
std::vector<MySingleElementFunc> mySingleElementFuncs;
std::vector<MyVectorFunc> myVectorFuncs;
};
template <typename T>
class MyTemplateBase {
// generic stuff goes here
};
template <typename T>
class MyTemplate : public MyTemplateBase<T> {
// nothing goes here
};
template <typename T>
class MyTemplate<std::vector<T>> : public MyTemplateBase <std::vector<T>> {
// specialized stuff goes here
}
If you don't want public inheritance you can use private inheritance, but then you would have to explicitly export everything inherited privately:
template <typename T>
class MyTemplate<std::vector<T>> : private MyTemplateBase <std::vector<T>> {
public:
// generic stuff re-exported
using MyTemplateBase<std::vector<T>>::Func1;
using MyTemplateBase<std::vector<T>>::Func2;
// specialized stuff goes here
}
Might still be worth it, as public inheritance is not exactly the most appropriate tool for code reuse.
I think that, since Vector is a template not a class, should be something like:
template<template <typename ...> class T /*= std::vector*/>
class SomeClass
{
T x;
};
I would like to make a class that has a function that saves the data sent to it, to a text file. The data that can be passed to it can be anything like a std::string, int, double, float, unsigned int, etc., and can also be an: std::vector<T>, T[], and std::vector<std::vector<T>>, T[][].
Now, obviously if it is an array, I will need to iterate through it to send the data to text-file.
I was thinking of using templates, but I'm not sure how to do the arrays.
Is this the way to go?
class CMyClass
{
template<typename T>
void SaveData(T data);
void SaveData(std::vector<T> data);
void SaveData(std::string data);
void SaveData(T* data); // Perhaps I'll also need to pass in the size.
void SaveData(std::vector<std::vector<T>> data);
void SaveData(T** data);
};
I imagine that the code for the std::string would be the same as the code for the std::vector<T> provided that T is a built in type (like an int or float or something).
And then I write the functions for each of the SaveData(...) accordingly?
First, you can either template the class or the functions. Since you want to do arrays as well, you must go with the latter option. Example follows:
class CMyClass
{
public:
template<typename T> void SaveData(const T &data);
template<typename T, size_t N> void SaveData(const T (&data)[N]);
template<typename T, size_t N, size_t M> void SaveData(const T (&data)[N][M]);
template<typename T> void SaveData(const std::vector<T> &data);
template<typename T> void SaveData(const std::vector<std::vector<T> > &data);
void SaveData(const std::string &data);
};
Once you have defined the functions, the following example shows how you can call them:
int i;
int i1[5];
int i2[5][7];
std::vector<int> v1;
std::vector<std::vector<int> > v2;
std::string s;
CMyClass saveClass;
saveClass.SaveData<int>(i);
saveClass.SaveData<int>(i1);
saveClass.SaveData<int>(i2);
saveClass.SaveData<int>(v1);
saveClass.SaveData<int>(v2);
saveClass.SaveData(s);
Depending on your requirements, you could make the class a singleton and the functions static, omitting the need to instantiate CMyClass at all and simply calling the functions as follows:
CMyClass::SaveData<int>(i);
CMyClass::SaveData<int>(i1);
CMyClass::SaveData<int>(i2);
CMyClass::SaveData<int>(v1);
CMyClass::SaveData<int>(v2);
CMyClass::SaveData(s);
Notes:
The arguments should also be references (i.e. "&data" rather than "data"), so that only the reference is passed rather than performing a copy of the whole container each time you call the function.
I've explicitly declared the functions as public, assuming this is the complete class and its functions will be accessed by another class. By default, the members of a class are private.
Ensure that there is a space between each nested ">".
Good luck!
I believe you're mixing two things in one class, which should be avoided: As far as I can see, what your class is about (its "responsibility") is to write data to a file. Another thing you're adding is knowledge about iterating collections of data.
Take a look at STL's <algorithm> methods:
http://www.cplusplus.com/reference/algorithm/
There you can find generic ways of iterating data, e.g. in the find method:
template<class InputIterator, class T>
InputIterator find ( InputIterator first, InputIterator last, const T& value )
{
for ( ;first!=last; first++) if ( *first==value ) break;
return first;
}
This makes you independent from whether you are using vector, list, arrays or whatever.
If you also want to serialize things like vector<vector<T> > (note the space between the two >!), you have to explain more on what you want to do with such data. Simply concat the elements as if all Ts were in one vector? In this case you might try to create a new iterator which does exactly this.
The boost iterator library could help with this:
http://www.boost.org/doc/libs/1_48_0/libs/iterator/doc/index.html
Let's say that I want to implement some classes for containers. All of them should implement such functions like insert, remove etc. So I write some interface:
template <class T>
class ContainerInterface {
public:
virtual void insert(T element) = 0;
template<class Predicate>
virtual void remove(Predicate p) = 0;
};
Now I can write something like:
template <class T>
class MyVector : public ContainerInterface<T>{};
template <class T>
class MyList : public ContainerInterface<T>{};
And I am sure that MyVector and MyList must implement functions insert and remove. However, there is the error:
error: templates may not be ‘virtual’
It comes from:
template<class Predicate>
virtual void remove(Predicate p) = 0;
I don't know the Predicate when I define some container and I dont'see any sense to bind deleter object to container class, for example one time I can pass Predicate to delete integers less than 50 and other time I want delete even integers. What can be done in such case - to declare some templated thing in base class and simulate virtual behaviour of function?
You can use type erasure with function objects. But luckily, the appropriate facilities already exist! For example, in your case, you could use boost::function<bool(const T&)> or std::function<bool(const T&)> (with TR1/C++11 support) as your predicate type!
virtual void remove(std::function<bool(const T&)> p);
Create some abstract class Predicate, which all concrete predicates will have to inherit from. Then, just make the predicate an argument to the function:
virtual void remove(Predicate* p) = 0;
You'll have to make the relevant Predicate member functions virtual of course, and let every concrete implementation override them.
I recently saw some code using macros like
#define CONTAINS(Class, Name)\
private:\
std::list<Class> m_##Name##s;\
public:\
void add_##Name(const Class& a_##Name) {\
m_##Name##s.push_back(a_##Name);\
}\
int get_##Name(int pos) {\
return m_##Name##s.at(pos);\
}\
// ... more member functions
Later you can declare a class like
class my_class {
CONTAINS(int, integer)
// ...
};
and write
my_class a(...);
a.add_integer(10);
I was puzzled about this paste-in-macro-style because I'm missing concrete counter-arguments. But beside that I accept the following pros
you can easily add a list interface for arbitrary types to your class
you avoid frequently repeated code
you have an easy to use interface (like add_integer(10))
Now I'm searching for alternatives which meet all these points above and avoid this old C macro style. My first idea was to create an abstract base class template
template<typename T>
class list_interface {
private:
std::list<T> m_list;
public:
void add_element(const T& x) {
m_list.push_back(x);
}
// ... more member functions
};
and add it to my class via inheritance like this
class my_class : public list_interface<int> {
// ...
};
Now I can write too
my_class a;
a.add_element(10);
but I'm concerned about the following points:
you can only add one list to your class
you publicly inherit from a class without virtual destructor
I don't meet the third point of the pros (add_element(10) instead of add_integer(10))
My questions are:
What are the drawbacks of the old C macro construct
How can I provide a similar functionality without macros
How about:
#include <vector>
template<typename T>
class Plop
{
std::vector<T> data;
public:
void add(T const& v) {data.push_back(v);}
T get(int pos) {return data.at(pos);} // at() is not valid on lists.
};
class my_class
{
public:
Plop<int> integer;
Plop<float> floater;
};
int main()
{
my_class x;
x.integer.add(5); // similar to x.add_integer(5);
x.integer.get(0); // similar to x.get_integer(0);
}
It meets all the requirements:
you can easily add a list interface for arbitrary types to your class
you avoid frequently repeated code
you have an easy to use interface (like add_integer(10))
My questions are:
What are the drawbacks of the old C macro construct
The ick factor.
Debugging.
Can pass individual list to other functions or methods.
How can I provide a similar functionality without macros
See above.
my opinion
1) Yuck yuck. Complex macro which will hinder debugging. Just the view of the macro makes my skin crawl.
2) Your inheritance solution looks fine. If you really needed multiple lists of different types, you might want to consider just writing more code and instantiating the list as a member variable. There really is no benefit of attempting to reduce lines of code by making it convoluted.
There is a way, in meta-programming fashion, and using tags.
First, let's consider the roll your own solution.
The idea is to come up with this interface:
class my_class : public vector<Name, std::string>, public vector<Foo, int>
{
};
And then, to use it like this:
my_class a;
a.add<Name>("Peter");
a.add<Foo>(3);
Now, lets dive behind the covers. We are going to use SFINAE combined with enable_if.
template <class Tag, class Type>
class vector
{
template <class T, Return>
struct Enable
{
typedef typename boost::enable_if<
boost::is_same<T,Tag>,
Return
>::type type;
}; // Enable
public:
template <class T>
typename Enable<T,void>::type
add(Type const& i) { m_elements.push_back(i); }
template <class T>
typename Enable<T, Type const&>::type
get(size_t i) const { return m_elements.at(i); }
// You'd better declare a whole lot of other methods if you really want that
// like empty, size and clear at the very least.
// Just use the same construct for the return type.
protected:
vector() : m_elements() {}
vector(vector const& rhs) : m_elements(rhs.m_elements) {}
vector& operator=(vector const& rhs) { m_elements = rhs.m_elements; return *this; }
~vector() {} // Not virtual, because cannot be invoked publicly :)
private:
std::vector<Type> m_elements; // at() is inefficient on lists
};
How does this work ?
Basically when you invoke get<Name> the compiler has 2 alternatives:
vector<Name,std::string>::get
vector<Foo,int>::get
Now, thanks to enable_if, the second alternative is ill-formed (the type deduced cannot be used because Foo != Name), and thus, thanks to SFINAE, this alternative is removed from the list without any complaint.
Then, since there is only one alternative, it gets selected. And of course, since this is done at compile-time, you don't actually have any runtime penalty.
If you want to skip some work (for this type). You could also simply use a simpler construct:
template <class Tag, class Embedded>
class Embed
{
// redeclares same private and protected interface
public:
template <class T>
typename Enable<T,Embedded &>::type get() { return m_element; }
template <class T>
typename Enable<T,Embedded const&>::type get() const { return m_element; }
private:
Embedded m_element;
};
Then you use it like so:
class my_class: public Embed< Names, std::vector<std::string> >,
public Embed<Foo,int>
{
};
my_class a;
std::vector<std::string> const& names = a.get<Names>();
int foo = a.get<Foo>();
a.get<Names>().push_back("Peter");
It's easier since you only provide accessors and don't have to write a whole bunch of methods just to forward the work.
And now that we've work so much, we should ask ourselves: this seems quite practical and generic, surely there is a library or something ?
There is >> Boost.Fusion's map:
class my_class
{
public:
template <class Tag>
typename result_of::at_key<map_type, T>::type &
get() { return at_key<T>(m_data); }
template <class Tag>
typename result_of::at_key<map_type, T>::type const&
get() const { return at_key<T>(m_data); }
private:
// First element of the pair: TAG
// Second element of the pair: Actual type of the data
typedef boost::fusion::map <
std::pair<Name, std::vector<std::string> >,
std::pair<Foo, int>
> map_type;
map_type m_data;
};
The main issue with the macro is: it is solving a problem you don't really have.
It is making a class with list members, where the lists are manipulated directly.
Because we think in OO, members should be encapsulated and we want to use DRY, we come to this construct, while my_class remains really a data-class.
If all the class has to do is contain lists, turn it into a struct and keep the lists public.
This way you have a clean intention and the lists can be accessed the STL-way.
If the class needs to have control over the lists, then you shouldn't expose the lists and the macro's are of little use.
So my code would be (not compiled):
struct my_class {
std::list<int> integers;
std::list<std::string> names;
// ...
};
int main()
{
my_class lists;
lists.integers.push_back(5);
size_t size_names = lists.names.size();
}
Pro:
easily add lists
no code duplication
consistent (STL) interface
straightforward
no macro's
Con:
no data encapsulation, if that would be a requirement
For multiple lists, you can try multiple inheritance with typedefs. Something like:
class my_class : public list_interface<int>, public list_interface<float> {
public:
typedef list_interface<int> Ints;
typedef list_interface<float> Floats;
//...
};
and use like:
my_class a;
a.Ints::add_element(10);
a.Floats::add_element(10.0f);