C++ : Vector of template class - c++

I have a template class named Cell as follows:-
template<class T>class Cell
{
string header, T data;
}
Now I want another class Named Row. Row will have a vector named Cells such that I can add both Cell and Cell type elements to that vector. Is it possible?
If so, how can I do that?
Thanks in advance.

With the extra detail you've provided, the first two answers won't work. What you require is a type known as a variant for the cell and then you can have a vector of those. For example:-
enum CellType
{
Int,
Float,
// etc
};
class Cell
{
CellType type;
union
{
int i;
float f;
// etc
};
};
class Vector
{
vector <Cell> cells;
};
This, however, is a pain to add new types to as it requires a lot of code to maintain. An alternative could use the cell template with a common base class:-
class ICell
{
// list of cell methods
};
template <class T>
class Cell : public ICell
{
T data;
// implementation of cell methods
};
class Vector
{
vector <ICell *> cells;
};
This might work better as you have less code initially to update to add a new cell type but you have to use a pointer type in the cells vector. If you stored the cell by value, vector <ICell>, then you will lose data due to object slicing.

The reason why this is NOT possible in C++, but possible in Java/Python is because: in a C++ vector, the STL container's storage (returned by vector::data()) contains all the object instantiations sequentially packed. In which each element must have the same size. This makes addressing fast and convenient. Therefore, suppose you define a template class A,
template <class T>
class A{
int id;
T obj;
};
Its size will depend on the template variable "T obj". Pushing the same class A of a different template type T will make each element in the vector have different sizes, thus, this is impossible. The only way is to use the vector of shared_ptr or unique_ptr of a base class. Both shared_ptr and unique_ptr are supported by C++11 and Boost. Each derived-class element can have different template types. In this way, when the base class pointer's destructor is called, the derived class's destructor will be invoked. For example,
#include <memory>
#include <vector>
#include <iostream>
#include <string>
using namespace std;
class A{};
template <class T>
class AImpl : public A{
public:
T obj;
AImpl(T _obj):obj(_obj){}
~AImpl(){
cout << "Deleting " << obj << endl;
}
};
int main(int argc, char** argv)
{
AImpl <string>* a1 = new AImpl <string> ("string1234");
AImpl <int>* a2 = new AImpl <int> (1234);
AImpl <double>* a3 = new AImpl <double> (1.234);
vector <shared_ptr<A>> As;
As.push_back(shared_ptr<A>(a1));
As.push_back(shared_ptr<A>(a2));
As.push_back(shared_ptr<A>(a3));
}
Remember to compile with -std=c++11 to enable C++11.
Output:
Deleting string1234
Deleting 1234
Deleting 1.234
And you get what you want! :)
In Java/Python, every class-object variable is actually a pointer, thus, a Java Array of A or a Python list of A is equivalent to a C++ array of pointers of A. Thus, you get essentially the same functionality without explicitly creating shared_ptrs.

The other answer is good, but you probably wanted:
template<class T>
class Row
{
private:
class Cell {
string header;
T data;
}
std::vector<Cell> cells;
...
}

Something like this?
template<class T>
class Row
{
private:
std::vector<Cell<T> > cells;
};
Okay, this answer is incorrect.
So, if you want to store in one vector different cells - you should use some dynamic type identification (you can use one base-class and store pointer to it in vector, that use only virtual functions, that are overrided in all derived classes, you can store something like boost::any and save some type-identification for each inserted element, for cast them into real type and work with it).

Related

How should I store templated functions in any container?

I have a templated Prob class that acts as a way to organize various programming problems from different problem sets. The template is the problem number. How would I go about storing different Prob objects in a vector or map?
Here is the class declaration:
template<int ProbNum>
class Prob
{
std::string
text(std::ostream& out)
{
out << "Prob" << ((ProbNum < 10) ? "0" : "") << ProbNum << ": ";
}
void solve(std::ostream& out);
};
So in other words if I want to declare an object for problem 1 of some problem set I would do
Prob<1> p1;
and then store that in a map or vector for later use so the user can call on it during runtime (since you cannot pass a runtime argument into a template).
Edit: I want to use this class as an abstract class for other Prob classes.
Edit2: Added more code for clarification.
Edit3:
Top half is Prob1.hpp
Bottom half is a driver file on how I want to use it.
#include <iostream>
#include "Prob.hpp"
template<>
void
Prob<1>::solve(std::ostream& out)
{
out << "solution to prob1";
}
/***************************************************/
#include <iostream>
#include <cstdlib>
#include "Prob.hpp"
// Finished Problems
#include "Prob1.hpp"
int
main(int argc, char* argv[])
{
Prob<1> p;
p.solve(std::cout);
}
Each instance of a template class constitutes a different type. Hence, containers like std::vector cannot hold Prob<ProbNum> for different values of ProbNum.
If you know at compile time the number of Prob<ProbNum> instances you want, and the corresponding values of the template parameter int ProbNum you could store everything into a tuple. For example:
auto mycollection = std::make_tuple(Prob<1>(), Prob<2>());
A more general solution could be to define an abstract base class for Prob. Then you can manage to store a vector of Prob<ProbNum> objects, with inhomogeneous values of int ProbNum, if you define a vector of pointers to the base class. For this to work you must provide the interface in the base class, i.e., every member of Prob<ProbNum> that you want to access through the vector of the base class, must be virtual and already declared in the base class.
Consider the following example:
#include <iostream>
#include <memory>
#include <vector>
struct base {
virtual void print() const = 0;
virtual ~base() = default;
};
template <int i>
struct derived : public base
{
virtual void print() const { std::cout << i << std::endl; }
};
int main()
{
std::vector<std::unique_ptr<base>> vec;
vec.emplace_back(new derived<1>());
vec.emplace_back(new derived<3>());
vec.emplace_back(new derived<5>());
for (auto& el : vec)
el->print();
return 0;
}
The variable vec is essentially a vector of pointers to objects of type derived<i>, with inhomogeneous values of i. Because base::print() is virtual, it correctly resolves to the corresponding method of the derived<i> class.
Notice that I used a smart pointer to avoid memory leaking.
Also, it is important to declare virtual the destructor of base, see the discussion Why should I declare a virtual destructor for an abstract class in C++?.

How to create a dynamic array that can hold different objects all derived from the same base class in C++

I have an assignment that doesn't allow me to use the vector class. I have a base class called Shape and different derived class such as Rectangle and Circle and i have to create my own vector class that has a dynamic array which can hold all these different shapes. I have used the following method that seems to work well
int **shape=new int*[capacity];
My problem comes with the "add_shape" function. I know how to add a shape individually using for example:
shape[0]=new Rectangle();
shape[1]=new Circle();
But how would one go about creating a universal function for adding a shape that could either be a rectangle or circle for instance.
Just wanted to elaborate on Nicky C's comment.
#include <memory>
using namespace std;
class Shape {};
class Rectangle : public Shape {};
class Circle : public Shape {};
template <class Type> class MyVector {}; // implement (with push method, etc.)
int main()
{
MyVector<unique_ptr<Shape>> v;
v.push(unique_ptr<Shape>(new Rectangle()));
v.push(unique_ptr<Shape>(new Circle()));
return 0;
}
The vector contains elements of type unique_ptr<Shape> which is the base class. Each element of the vector can be unique_ptr<Rectangle> or unique_ptr<Circle> as well. However, if the vector were of type unique_ptr<Rectangle>, each element would have to be of type unique_ptr<Rectangle> (i.e. it could not be of type unique_ptr<Circle>).
Since you are allocating memory on the heap, using unique_ptr just makes sure that you don't need to call delete yourself.
One of the strengths of inheritance/polymorphism is that you can use a derived class wherever a base class is needed. It is an important key concept. For instance, as in your code above, you can do:
Shape *s = new Shape();
s = new Rectangle();
s = new Circle();
This also applies to function parameters:
class DynamicArray
{
private:
Shape **_shapes[];
...
public:
void add_shape(Shape *s)
{
// Add the shape to _shapes;
}
...
};
void main()
{
DynamicArray array;
array.add_shape(new Shape()):
array.add_shape(new Rectangle()):
array.add_shape(new Circle()):
}

Is there a way to specify the type of a class member based on the input type to a constructor?

I am using a matrix library (Eigen) where the sizes of the matrices affect the type of the matrix. I am trying to create a class that is initialized with a constructor that takes a matrix and copies it over to the member matrix. Since this is a library, I would like to do this so that the user doesn't have to know the size of their matrix when they initialize my matrix class (because maybe their matrix is coming from another file)
Basically I would like something like the code below, where unknownType takes the form of someType upon being constructed
class Matrix{
private:
unknownType m1;
public:
Matrix(someType m2): m1(m2){}
};
#BenSteffan is right.
It's what templates were made for.
Here is an absolutely toy example.
#include <iostream>
template<typename ELEMENT_TYPE>
class Matrix {
private:
ELEMENT_TYPE element;
public:
Matrix(ELEMENT_TYPE value):element(value){}
ELEMENT_TYPE get(){
return element;
}
};
int main() {
Matrix<double> dmatrix(78.7);
Matrix<int> imatrix(7000);
std::cout<<dmatrix.get()<<' '<<imatrix.get()<<std::endl;
return 0;
}

Passing vectors of derived shared pointers?

What is the proper way to allow vectors of shared pointers to a derived class to get passed to a function which is expecting a vector of shared pointers to a base class without performing a copy?
Here is the code:
#include <string>
#include <vector>
#include <memory>
class Base {
public:
std::string Name;
};
using BaseList = std::vector<std::shared_ptr<Base>>;
class Derived : Base {
};
using DerivedList = std::vector<std::shared_ptr<Derived>>;
class BaseHandler {
public:
void process( BaseList list ) {
}
};
int main() {
DerivedList list;
BaseHandler bh;
bh.process( list );
}
Code Link: http://coliru.stacked-crooked.com/a/5a5b18ba3b2a4f08
EDIT: DOH!!! I posted the wrong one. Sorry about that...here is the shared_ptr one.
You may try this.
template <class T,
class SharedPtr = typename T::value_type,
class Element = typename SharedPtr::element_type,
class IsDerived = typename std::enable_if<std::is_base_of<Base, Element>::value, void*>::type
>
void process(const T& t) { std::cout << "process" << std::endl; }
The key ideas are:
Instead of accessing the elements through base class pointers, we can access the them through their concrete type information known by the compiler.
This function template uses a trick called "SFINAE" to check whether the parameter is a container of smart pointer of derived class.
Follow up:
Conversion from "container of shared pointer to derived class" to "container of shared pointer to base class" is possible and not very difficult. However, I concern whether the design choice of using "container of shared pointer to base class" will give you acceptable performance.
Let's discuss how to do it first.
We can create a std::shared_ptr<Base> object from each std::shared_ptr<Derived> object by using std::static_pointer_cast.
To apply std::static_pointer_cast on everything entries of the list, we can use std::transform.
If you have many derived classes, the conversion can be made available to every derived classes by using a function template with SFINAE check as mentioned.
So, the code looks like:
DerivedList derivedList;
// Put items into derivedList
BaseList baseList;
baseList.reserve(derivedList.size());
std::transform(std::begin(derivedList), std::end(derivedList), std::back_inserter(baseList),
[](const std::shared_ptr<Derived>& shptr)
{
return std::static_pointer_cast<Base>(shptr);
});
BaseHandler bh;
bh.process(baseList);
Or:
class BaseForwarder
{
public:
template <class T,
class SharedPtr = typename T::value_type,
class Element = typename SharedPtr::element_type,
class IsDerived = typename std::enable_if<std::is_base_of<Base, Element>::value, void*>::type
>
void process(const T& derivedList)
{
BaseList baseList;
baseList.reserve(derivedList.size());
std::transform(std::begin(derivedList), std::end(derivedList), std::back_inserter(baseList),
[](const SharedPtr& shptr)
{
return std::static_pointer_cast<Base>(shptr);
});
BaseHandler bh;
bh.process(baseList);
}
};
However, this approach has quite a lot of performance penalty.
A new list of pointer to base class has to be created for each list of pointer to derived class. It spends a lot of time and memory to construct the new list.
The objects are accessed through pointers. This indirection slow things down.
Since the objects are not allocated into compact data structure, cache misses will be severe.
I suggest you to evaluate the performance to see whether this approach is acceptable. Otherwise, it is better to consider some other design choices.

C++ making a template class as place holder in another class

I am trying to make a template class as placeholder class which can hold something like and string and type T object. Below is the code which I have written for the same.
#include <iostream>
#include <string>
#include <map>
using namespace std;
//A class which act as placeholder to hold
//unknown object. Something similar as Object
//in Java
template <typename T>
class Genric
{
public:
map<string, T> addP; //This will be placeholder for time
// being.
};
class A
{
public:
Genric t1; //Have object of Genric class so that we can
// access the member variable in future.
void foo()
{
cout<<"Calling foo"<<endl;
}
};
int main()
{
A a1;
a1.foo();
}
But when I tried to compile I am getting below error.
$ g++ tempClass.cxx
tempClass.cxx:21:9: error: invalid use of template-name 'Genric' without an argument list
The purpose of above Genric class is just to act as placeholder class for one of the member variables which can be populated in future.
So is there a way we can write such Genric class.
You are defining Genric as a template class, but then trying to initialize t1 without giving a type to it. That is the error you are getting. Try for example:
Genric<int> t1;
Or, if you are looking for a truly runtime generic, look into boost::any.
You need something like boost::any:
map<string, boost::any> anywayzz;
You can store any object in it. You don't need Genric class template.
If you're not using boost, then you can implement any yourself. Look for its implementation, or type-erasure, on this site. You will surely get some idea. Start from here:
Type erasure techniques
A template is "generic" until the program is compiled. At that point the compile must be made aware of what types it has to deal with.
If you want something that can contain a compile-time unknown (better: not yet known) type template are not the solution. Since the actual type will be known just at runtime, you have to go towards runtime-based polymorphism (inheritance from a polymorphic base) eventually wrapped inside an "handler".
In essence you need a base with at leas t a virtual function that allow you to check the type, and generic derived class that implement that function in a suitable way for all types.
boost::any can be an implementation, but there can be simpler ways, especially considering that "a function that allows to discover a runtime type" is no more than ... dynamic_cast.
You can so cometo a solution like this
#include <memory>
class any_value
{
template<class T>
class wrapper; //see below
class common_base
{
public:
virtual ~common_base() {} //this makes the type polymorphic
template<class T>
T* has_value()
{
auto* ptr = dynamic_cast<wrapper<T>*>(this);
return ptr? &ptr->m: nullptr;
}
};
template<class T>
class wrapper: public common_base
{
public:
wrapper() :m() {}
wrapper(const T& t) :m(t) {}
T m;
};
std::unique_ptr<common_base> pb;
public:
any_value() {}
template<class T>
any_value(const T& t) :pb(new wrapper<T>(t)) {}
template<class T>
any_value& operator=(const T& t)
{ pb = std::unique_ptr<common_base>(new wrapper<T>(t)); return *this; }
any_value(any_value&&) =default;
any_value& operator=(any_value&&) =default;
//NOW THE GETTERS
template<class T>
T* get() const //nullptr if not holding a T*
{ return bool(pb)? pb->has_value<T>(): nullptr; }
template<class T>
bool get(T& t)
{
T* pt = get<T>();
if(pt) t = *pt;
return bool(pt);
}
};
#include <iostream>
#include <string>
int main()
{
any_value a(5), b(2.7192818), c(std::string("as a string"));
int vi=0; double vd=0; std::string vs;
if(!a.get(vi)) vi=0; //will go
if(!a.get(vd)) vd=0; //will fail
if(!a.get(vs)) vs.clear(); //will fail
std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
if(!b.get(vi)) vi=0; //will fail
if(!b.get(vd)) vd=0; //will go
if(!b.get(vs)) vs.clear(); //will fail
std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
if(!c.get(vi)) vi=0; //will fail
if(!c.get(vd)) vd=0; //will fail
if(!c.get(vs)) vs.clear(); //will go
std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
}
Following Abhinav comment:
Since the C++ type system is static, you cannot -in general- deserialize an "unknown", unless you first deserialize something that can be "Known".
For this you first need a way to represet a C++ type (not object) into an recognizable value (sort of type-uid), and a "factory" that creates the wrappers appropriated for those "values".
On saving, you just save that uid, then ask via a common_base virtual function to save the wrapped value.
On loading, you first load the uid, than create a new wrapper with appropriate type (see after) and than load the value via a common_base virtual function.
To create an appropriate wrapper, you need a table that maps the uid-s towards functions that create the wrapper associated with the type uid.
This table must be pre-initialized for all the types you need to be able to serialize / deserialize.
But this goes long away your original question, that doesn't speak about serialization/deserialization.
If the problem is "serialization", the "type erasure" is not a complete solution. You should much more look at the "factory pattern". And post another question better suited for that argument.