I am trying to have a container of template elements but it's not compiling because the first argument is not given
So I want to put the following class in a std::map
template <typename T>
class TemplateParam
{
ITemplateParam<T> param_;
public:
TemplateParam(T value)
{
if (sizeof(value) >= sizeof(void*))
param_ = ptrTemplateParam<T>(value);
else
param_ = cpyTemplateParam<T>(value);
}
const T &getParam() const { return param_.getParam(); }
};
ITemplateParam
template <typename U>
class ITemplateParam
{
public:
virtual ~ITemplateParam(){}
virtual const U& getParam() const = 0;
};
I think I understand why I can't put elements of different sizes in a container, it's why I used ptrTemplateParam and cpyTemplateParam. (I have also tried with the shared_ptr)
Do you have any idea how can I resolve my problem
I can use boost library
I have looked at this link but I don't know how can I declare the getter.
Edit:
Thanks to your answer I am able to store it in a map but I'm not able to insert an element in the map and I have to use void*
So I have changed my class to:
class ITemplateParam
{
public:
virtual ~ITemplateParam(){}
virtual const void *getParam() const = 0;
};
template <typename U>
class ptrTemplateParam : public ITemplateParam
{
U param_;
public:
ptrTemplateParam(U & param) : param_(param) {}
virtual const void *getParam() const { return param_; }
};
class TemplateParam
{
std::shared_ptr<ITemplateParam> param_;
public:
template <typename T>
TemplateParam(T value): param_(ptrTemplateParam<T>(value))
{
}
const void *getParam() const { return param_->getParam();}
};
and I try to do
std::map<std::string, TemplateParam> m_;
m_["integer"] = TemplateParam(5);
Edit2
boost::any was the solution
If you need to have a container that contains elements of different type then you have
basically 3 ways:
Have container of variants or unions.
Have container of polymorphic pointers or polymorphic smart pointers.
Use intrusive container.
It is unclear from your question what would be best for you.
IMHO, if you want to put different items in the same container, you should consider using Boost.Variant. This is not a direct answer to your actual example here, but I found this pattern very useful for this category of problems. You avoid using pointers and enforcing inheritance in an elegant way.
class A {};
class B {};
typedef boost::variant<A, B> item_t;
...
vector<item_t> my_container;
Related
I am trying to create an adapter of a custom collection MyArray<T>.
For simplicity, the adapter Adapter does only one thing : cast the return result of MyArray<T>::get.
(In real case, MyArray and Adapter are very complex database manipulators.)
Version 1
Here is the first version, it works. (demo)
#include <iostream>
using namespace std;
template<class T>class MyArray{
public: T* database[20];
public: T* get(int index){return database[index];} //<-important
public: void set(int index,T* t){database[index]=t;}
};
template<class T,class T2> class Adapter{
public: MyArray<T>* underlying;
public: void setUnderlying(MyArray<T>* pUnder){underlying=pUnder;}
public: T2* get(int index){return static_cast<T2*>(underlying->get(index));}
//^ "Adapter::get()" is encapsulating "MyArray::get()"
};
class B{};
class C:public B{};
class D:public C{};
int main() {
MyArray<B> bs;
bs.set(0,new C()); //some can be new D()
//About the Adapter<C>, user is the one who sure that "bs" elements are "C*"-castable.
Adapter<B,C> cs; //<-- #1 need improve
cs.setUnderlying(&bs); //<-- assign MyArray* to adapter
C* c=cs.get(0);
return 0;
}
Version 2
Then, I want to sacrifice performance for readability and convenience. (#1)
Objective: Reduce amounts of template parameters of from 2 (Adapter<B,C>) to 1 (Adapter<C>).
Here is my work so far. It is compilable but should crash in some cases:-
class MyArrayBase{ //<--- new class
public: virtual void* get(int index)=0;
};
template<class T>class MyArray : public MyArrayBase{
public: T* database[20];
public: T* get(int index){return database[index];}
public: void set(int index,T* t){database[index]=t;}
};
template<class T2> class Adapter{
public: MyArrayBase* underlying; //<--- more abstraction
public: void setUnderlying(MyArrayBase* pUnder){underlying=pUnder;}
public: T2* get(int index){return static_cast<T2*>(underlying->get(index));} //#wrong
};
class B{};
class C:public B{};
int main() {
MyArray<B> bs;
bs.set(0,new C());
Adapter<C> cs; //<--- Yes! 1 template argument.
cs.setUnderlying(&bs);
C* c=cs.get(0);
std::cout<<"hi"<<std::endl;
return 0;
}
The reason that it is wrong :-
At the #wrong, void* (underlying B*) is static_cast to C*.
Here is the demo shows that it is wrong. (print 0 instead of 5)
Question
How to improve my first version of code to make Adapter have less template parameter?
Criteria :-
Don't use function pointer.
I feel it is possible with function pointer or std::function, but it seems to be a hack.
I also want to know if it is possible without using it.
Overhead should not be (roughly) worse than a single virtual calling (v-table) as in Version 2.
A single instance of Adapter<C>::setUnderlying must be able to accept any MyArray<X>* when it makes sense to call static_cast<C*>(X*).
MyArray and Adapter are library class. It doesn't have any knowledge about the type T or T2.
For example, I can't replace void* in class MyArrayBase with B*.
Light criteria :-
I prefer a solution using virtual function.
It would be ideal if there is no virtual-cost, but I don't think it is possible.
You can use some kind of wrapper that wraps the container, typically:
// Here T = T2, you want a virtual function that already give you the right type
template <typename T>
class Wrapper {
public:
virtual T* get(int index) const = 0;
};
// The real wrapper: It can give you T2 (To) but keep information
// about the original type since it is templated on Container
template <class To, class Container>
class WrapperContainer: public Wrapper<To> {
Container *cont_;
public:
WrapperContainer(Container *cont) : cont_(cont) { }
virtual To* get(int index) const override {
return static_cast<To*>(cont_->get(index));
}
};
The wrapper is the middle-guy between your Adapter that only knows the To type (the type you want to convert to) and your MyArray that only knows the From type (the type you want to convert from) - The WrapperContainer knows both, so it can safely convert from one to the other when it is possible.
The final Adapter:
template<class T2>
class Adapter {
std::unique_ptr<Wrapper<T2>> w_;
public:
template <typename Container>
void setUnderlying(Container *cont) {
w_ = std::unique_ptr<Wrapper<T2>>(new WrapperContainer<T2, Container>(cont));
}
T2* get(int index) {
return w_->get(index);
}
};
Using this you do not want a base class for MyArray since you need setUnderlying to deduce the type B from MyArray<B>:
// No more need for a base class
template<class T>
class MyArray {
T* database[20];
public:
T* get(int index){return database[index];}
void set(int index,T* t){database[index]=t;}
};
The important change from your code is actually this line:
return static_cast<To*>(cont_->get(index));
The type of cont_->get(index) is B* (in this example) and not void*, which makes the conversion work. This also prevents using setUnderlying with array of non-compatible type (try to uncomment the line cs.setUnderlying(&as); in the code below).
You can test it here: http://coliru.stacked-crooked.com/a/116305ec5f18b673
I want to create a templated API to access derived types that are stored in a vector of vectors. The outer vector has an element for each derived type. The inner vector has a collection of those types.
std::vector<std::vector<MyBaseClass>* > items;
Ideally, I would like to provide an API where derived types of MyBaseClass can be added and accessed (without specialized templates). Something like this:
T& addItem(size_t index, T& item);
T& getItem(size_t index);
Use like this:
AClass : public MyBaseClass {};
BClass : public MyBaseClass {};
addItem<AClass&>(123, item);
addItem<BClass&>(456, item);
AClass& = getItem<AClass&>(123);
BClass& = getItem<BClass&>(456);
The reason for the lack of specialized templates is that I want to enable the use of new derived types without other developers having to modify this code.
So, is there a way I can get this kind of API implemented without having to know the derived class types and specialize the code?
Is it possible to do this with a union and template?
Note: The inner vector needs to store its data consecutively in memory, so I am not using pointers.
Note: I am using C++11 without Boost.
Thanks.
Something along these lines perhaps:
class FancyStore {
public:
template <typename T>
T& addItem(const T& item) {
void*& raw = store_[typeid(T)];
if (!raw) {
raw = new std::vector<T>();
}
auto v = static_cast<std::vector<T>*>(raw);
v->push_back(item);
return v->back();
}
template <typename T>
T& getItem(size_t index) {
void* raw = store_[typeid(T)];
auto v = static_cast<std::vector<T>*>(raw);
return (*v)[index];
}
private:
std::unordered_map<std::type_index, void*> store_;
};
Live demo. Copying, destructor, error handling are left as an exercise for the reader.
I have an abstract class (I know that it will not compile this way, but it's for comprehension of what I want to do) :
class AbstractComputation {
public:
template <class T> virtual void setData(std::string id, T data);
template <class T> virtual T getData(std::string id);
};
class Computation : public AbstractComputation {
public:
template <class T> void setData(std::string id, T data);
template <class T> T getData(std::string id, T data);
};
So when I call setData<double>("foodouble", data) I want the double identified by foodouble (internal mechanism which is not the main concern here) to be set to the double data.
So how to do that?
I think that there may be a mean by typing something like virtual void setData<double>(std::string id, double data) but I don't know how to do it.
The problem is that you cannot mix static time polymorphism (templates) with runtime polymorphism easily. The reason for the language disallowing the particular construct in your example is that there are potentially infinite different types that could be instantiating your template member function, and that in turn means that the compiler would have to generate code to dynamically dispatch those many types, which is infeasible.
There are different things that can be done here to get around the limitation, basically either take away the static or the dynamic polymorphism. Removing dynamic polymorphism from the equation could be done by providing a type that is not derived from, to store the <key,value> mappings, and then offering the template that resolves that only at the base level:
class AbstractComputation {
public:
template <typename T>
void setData( std::string const & id, T value ) {
m_store.setData( id, value );
}
template <typename T>
T getData( std::string const & id ) const {
return m_store.getData<T>( id );
}
protected:
ValueStore m_store;
};
Now deriving classes can access the ValueStore from the base and there is no need for polymorphism. (This can also be done by implementing the functionality directly in AbstractComputation but it probably makes sense to separate concerns)
The other option is to maintain runtime polymorphism, but remove static polymorphism. This can be done by performing type erasure on the base class and then dispatching to the appropriate (non-templated) function that takes the type-erased arguments. The simplest version of this is just using boost::any:
class AbstractComputation {
public:
template <typename T>
void setData( std::string const & id, T value ) {
setDataImpl( id, boost::any( value ) );
}
template <typename T>
T getData( std::string const & id ) const {
boost::any res = getDataImpl( id );
return boost::any_cast<T>( res );
}
protected:
virtual void setDataImpl( std::string const & id, boost::any const & value ) = 0;
virtual boost::any getDataImpl( std::string const & id ) const = 0;
};
How type erasure is implemented under the hood is interesting, but out of the scope here, the important part is that a boost::any is a concrete (non-templated) type that can store any type internally by using type erasure on the arguments, and at the same time allows for type-safe retrieval of the data.
In some cases it may be enough to move the templating from method level to class level, e.g.:
#include <iostream>
template<typename T>
class AbstractComputation {
public:
virtual void setData(std::string id, T data)
{
std::cout << "base" << std::endl;
}
};
template<typename T>
class Computation : public AbstractComputation<T> {
public:
virtual void setData(std::string id, T data)
{
std::cout << "derived" << std::endl;
}
};
int main()
{
AbstractComputation<int> *x = new Computation<int>();
x->setData("1", -1);
delete x;
return 0;
}
You can probably use boost::any in your case.
virtual void setData(std::string id, boost::any data);
It is a wrapper that can encapsulate almost anything.
More info on a similar topic in this answer.
First, you cannot have virtual template functions. As templates are resolved at compile time, virtual will not work, as the compiler would not know which template to pick. See here, for more info about this.
If you know list of possible types in advance, preprocessor may help:
#define MY_CLASSES MYTYPE(int) MYTYPE(float) MYTYPE(double)
class AbstractComputation {
public:
# define MYTYPE(T) virtual void setData(std::string id, T data)=0;\
virtual void getData(std::string id, T& dst_data)=0;
MY_CLASSES
# undef MYTYPE
};
class Computation : public AbstractComputation {
public:
# define MYTYPE(T) virtual void setData(std::string id, T data){std::cout<<"writing: "<<data<<std::endl;}\
virtual void getData(std::string id, T& dst_data){dst_data=0;/*put your actual implementation here*/}
MY_CLASSES
# undef MYTYPE
};
If you don't know a complete list of possible types, perhaps, your problem is unresolvable. Type erasure, as mentioned by others, may also help.. but not in all circumstances.
Use boost::any to accept the datum, and then when you actually set, grab the correct type from it.
I have no idea if the title makes any sense but I can't find the right words to descibe my "problem" in one line. Anyway, here is my problem. There is an interface for a search:
template <typename InputType, typename ResultType> class Search {
public:
virtual void search (InputType) = 0;
virtual void getResult(ResultType&) = 0;
};
and several derived classes like:
template <typename InputType, typename ResultType>
class XMLSearch : public Search<InputType, ResultType> {
public:
void search (InputType) { ... };
void getResult(ResultType&) { ... };
};
The derived classes shall be used in the source code later on. I would like to hold a simple pointer to a Search without specifying the template parameters, then assign a new XMLSearch and thereby define the template parameters of Search and XMLSearch
Search *s = new XMLSearch<int, int>();
I found a way that works syntactically like what I'm trying to do, but it seems a bit odd to really use it:
template <typename T> class Derived;
class Base {
public:
template <typename T>
bool GetValue(T &value) {
Derived<T> *castedThis=dynamic_cast<Derived<T>* >(this);
if(castedThis)
return castedThis->GetValue(value);
return false;
}
virtual void Dummy() {}
};
template <typename T> class Derived : public Base {
public:
Derived<T>() {
mValue=17;
}
bool GetValue(T &value) {
value=mValue;
return true;
}
T mValue;
};
int main(int argc, char* argv[])
{
Base *v=new Derived<int>;
int i=0;
if(!v->GetValue(i))
std::cout<<"Wrong type int."<<std::endl;
float f=0.0;
if(!v->GetValue(f))
std::cout<<"Wrong type float."<<std::endl;
std::cout<<i<<std::endl<<f;
char c;
std::cin>>c;
return 0;
}
Is there a better way to accomplish this?
Is there a better way to accomplish
this?
Yes, that design is slightly better, since that's using static-dispatching while calling GetValue() (I'm assuming that dynamic_cast is typo, you actually wanted to type static_cast in Base::GetValue()). In that design, Base::GetValue() is not virtual, yet it is able to call Derived::GetValue() using pointer of type Base. This makes it slightly fast.
But even your way is not that bad. All you've to instantiate your class templates like this:
Search<int,int> *s = new XMLSearch<int, int>();
Your Search *s = new XMLSearch<int, int>() is wrong!
You can typedef your templates as follows:
typedef Search<int,int> iisearch;
typedef XMLSearch<int,int> iixmlsearch;
Then use them:
iisearch *s = new iixmlsearch();
This looks better, right?
Small Modification
You can make your class slightly better performance-wise. For that, write your Search class template as follows:
template <typename InputType, typename ResultType> class Search {
public:
void search (InputType input) //it's not virtual anymore!
{
xmlsearch *_this = getXmlSearch();
xmlsearch->search(input);
}
void getResult(ResultType& result) //it's not virtual anymore!
{
xmlsearch *_this = getXmlSearch();
xmlsearch->getResult(result);
}
private:
typedef XMLSearch<InputType, ResultType> xmlsearch;
xmlsearch* getXmlSearch()
{
static xmlsearch *_this= static_cast<xmlsearch* >(this);
return _this;
}
};
Now your base class is not abstract, as it doesn't define virtual functions. This design is slightly faster than your version!
let's say i want to have a member variable for a pointer to std::vector but i do not want to specify what type of variable it stores. I want to access only those functions that are independant of it's actual generic type. is this possible with c++? something like this:
class Foo{
public:
void setVec(std::vector* someVec){
myVec = someVec;
};
int getSize(){
return myVec.size();
};
private:
std::vector* myVec;
};
int main(){
Foo foo;
vector<int> vec1;
vector<float> vec2;
foo.setVec(&vec1);
cout<<foo.getSize();
foo.setVec(&vec2);
cout<<foo.getSize();
}
note: i do not want to template Foo and i want to use only a single instance of Foo with vectors of different type.
of course - if I could alter the class vector then i could create an untemplated baseclass
class Ivector{
virtual int size()=0;
};
and then make the
class vector<T> : public IVector...
inherit from Ivector. but what do I do if i can't alter the class in question and the templated class does not have such an untemplated baseclass?
thanks!
You are almost at the answer. Instead of making std::vector inherit from Ivector, create a new class:
template <typename T>
class IVectorImpl : public Ivector
{
public:
explicit IVectorImpl(std::vector<T> * Data) : m_Data(Data){}
std::vector<T> * m_Data;
...
virtual int size() const {return m_Data->size();}
// Implement all the Ivector functions here to call the respective functions off of m_Data
};
Now have your Foo class keep a pointer to Ivector instead of std::vector.
Make Foo::setVec templated
template <typename T>
void setVec(std::vector<T> * vec)
{
Ivector * newVec = new IVectorImpl<T>(vec);
delete myVec;
myVec = newVec;
}
You could do this:
class vector_container_base
{
public:
~vector_container_base() {}
virtual std::size_t size() const = 0;
};
template <typename T>
class vector_container :
public vector_container_base
{
public:
typedef std::vector<T> vector_type;
std::size_t size() const
{
return mVector.size();
}
private:
vector_type mVector;
};
And so on, but I doubt this is too useful in any real situation.
The line
std::vector* myVec
is not syntactically correct. One has to specify the type of the vector elements.
You may want to do something on the line of
template< typename T >
class Foo{
private:
std::vector<T> * myVec;
};
However, even that doesn't look nice, re-evaluating the design might be more important here.