Adapter of collection - omit T that depends on underlying collection - c++

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

Related

CRTP and lifetime extension

My question is how to make lifetime extension work with CRTP. For example, the following code is perfectly valid:
struct A {
const int& ref;
};
struct B {
const A& a;
};
int main() {
B b{{123}};
return b.a.ref;
}
Its CRTPed version is not:
template <class DerivedT>
class Gettable {
public:
int Get() const {
return static_cast<const DerivedT*>(this)->GetImpl();
}
};
class A : public Gettable<A> {
friend class Gettable<A>;
public:
A(int r) : ref{r}{}
private:
int GetImpl() const {
return ref;
}
const int& ref;
};
template <class T>
class B {
public:
B(const Gettable<T>& gettable) : get_{gettable}{}
int DifferentGet() const {
return get_.Get();
}
private:
const Gettable<T>& get_;
};
int main() {
B b{A{123}};
return b.DifferentGet();
}
The problem is that the original A and its Gettable<A> subobject only exist till the the of B constructor.
I have two questions:
1) Why? It is in no way different from the first case of structs, every lifetime is known at compile time, so I believe that compiler should be able to extend lifetime of all temporaries.
2) Is there any good way to overcome this issue?
1) Why?
Because there is a function involved - the constructor. The temporary is not bound directly to the member, but rather it is bound directly to the argument of the function - whose lifetime extends until the end of the function, which does not extend beyond the full expression that invoces the function.
It is in no way different from the first case of structs
It is different. There is no constructor involved in aggregate initialisation. In that case, the compiler knows the lifetime of the member, and it knows that the member is initialised with the temporary. The lifetime extension rule applies.
so I believe that compiler should be able to extend lifetime of all temporaries.
Consider following example:
struct foo {};
struct bar {
bar(const foo& farg);
const foo& fmem;
};
bar b({});
Should the lifetime of the temporary to extend for the lifetime of b? The standard says, that it doesn't. You appear to be arguing that it should.
Consider following possible implementations of the constructor:
bar::bar(const foo& farg) : fmem{farg} {} // 1
foo fanother;
bar::bar(const foo& farg) : fmem{fanother} {} // 2
If the implementation happens to be 1, then you guessed right, the life time extension is needed. If implementation is 2, then we are unnecessarily extending a temporary that is not referred to anymore.
The language designers chose to not extend such temporary, probably so that life times of temporaries don't get extended unnecessarily. As a consequence, implementation 1 is wrong, as well as your CRTP example.
Concisely: The compiler can only extend the lifetime of a temporary until the lifetime of the reference to which the temporary is bound directly. The compiler cannot know what will be done with the reference within the function. It cannot know that an argument has something to do with a member. Those are only known when the constructor is compiled - not when a call to the constructor is compiled.
2) Is there any good way to overcome this issue?
Use either int* or std::reference_wrapper<int> as the constructor argument. Former is more concise, but latter has convenient property of not having a null representation. These should make it harder to accidentally bind a dangling reference. Regardless, document carefully that the referred object must still be valid when Get is called.
I believe that the most general solution is something like this. This way it works even for multilevel inheritance.
#include <iostream>
#include <utility>
#include <type_traits>
struct NullType {};
// Helper class for casting
template <class Derived>
class DerivedCaster {
protected:
Derived* GetDerived() {
return static_cast<Derived*>(this);
}
const Derived* GetDerived() const {
return static_cast<const Derived*>(this);
}
};
// Matches the predicate against the types and remembers the first
// satisfying argument
template <template <class T> class Predicate, class... Args>
struct FindFirstMatching {
using Type = ... ; // default NullType
static const bool has_match = ... ;
};
// Structure which gets the deepest class from CRTP inheritance chain
// by looking at the instantiated parent class template
template<typename T>
struct GetDeepest
{
using Type = T;
};
template<template<class...> class DT, class... T>
struct GetDeepest<DT<T...>>
{
template <class CLS>
struct Predicate {
static const bool value = std::is_base_of<DT<T...>, CLS>::value;
};
static const bool HasCRTPDerived = FindFirstMatching<Predicate, T...>::has_match;
using DerivedT = typename FindFirstMatching<Predicate, T...>::Type;
using Type = std::conditional_t<HasCRTPDerived, typename GetDeepest<DerivedT>::Type, DT<T...>>;
};
// First abstract class
template <class DerivedT>
class Gettable : public DerivedCaster<DerivedT> {
public:
int Get() const {
return DerivedCaster<DerivedT>::GetDerived()->GetImpl();
}
};
// Second abstract class
template <class DerivedT>
class Incrementable : public DerivedCaster<DerivedT>,
public Gettable<Incrementable<DerivedT>> {
friend class Gettable<Incrementable<DerivedT>>;
public:
int Increment() const {
return ++(this->Get());
}
private:
int GetImpl() const {
return DerivedCaster<DerivedT>::GetDerived()->GetImpl() + 100;
}
};
// non-abstract class
class A : public Incrementable<A> {
friend class Incrementable<A>;
public:
A(int r) : ref_{r}{}
private:
int GetImpl() const {
return ref_;
}
int ref_;
};
// Helper to get the copy of the underlying non-abstract class
template <class T>
auto GetDeepestLevelCopy(const T& arg) {
return static_cast<const typename GetDeepest<T>::Type&>(arg);
}
// Some other class which wants a copy
template <class T>
class B {
public:
B(const Gettable<T>& gettable) : get_{GetDeepestLevelCopy(gettable)}{}
int DifferentGet() const {
return get_.Get();
}
private:
typename GetDeepest<Gettable<T>>::Type get_;
};
int main() {
static_assert(std::is_same_v<GetDeepest<Gettable<Incrementable<A>>>::Type, A>);
static_assert(std::is_same_v<decltype(GetDeepestLevelCopy(std::declval<Gettable<Incrementable<A>>>())), A>);
B b{A{123}};
std::cout << b.DifferentGet() << "\n";
// prints 223
return 0;
}
This looks monstrous, but I don't know whether there is a better solution.

CRTP and method returning void *

I use C++ 11. I have a Base class and several derived classes for parsing different configuration files line by line.
template <class T>
class Base
{
public:
virtual ~Base();
bool load_from_file(const QString& str);
virtual void* get_data(const QString& str) const = 0;
private:
QList<QSharedPointer<T> > items_;
};
Each descendant (class Derived: public Base<My_struct>) must provide get_data() implementation.
Each My_struct instance contains information from certain line of a settings file.
For example, imagine a typical file with a list of proxies.
My_struct instances are wrapped in smart pointers in Base class in the load_from_file() method and appended to the items_ member. load_from_file() method casts void* to T* before wrapping.
Is it possible to redesign these classes in order to avoid using void* (and without libraries like boost::any)?
I mean considering CRTP and so on. Usually CRTP examples contain methods of derived classes with void return values (like procedures in Pascal).
Bro! Try to switch to C++14 and use the following snippet as a hint:
template <typename Derived>
struct base
{
template <typename T>
auto f(T x)
{
return static_cast<Derived&>(*this).f_impl(x);
}
auto g()
{
return static_cast<Derived&>(*this).g_impl();
}
};
struct derived : base<derived>
{
bool f_impl(int x)
{
return true;
}
double g_impl()
{
return 4.2;
}
};
This fragment has been taken from here.

How can I have a container of template elements

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;

How to implement function with vector of derived classes as parameter

(Related to a previous unanswered question I asked). I want to implement a function which can be called only with vectors of related classes as parameter.
For eq
if we have
class A;
class B: public A;
class C: public A;
class D
then it should be possible to call function with vector<A*>,vector<B*> or
vector <C*> but not vector <D*>
Any suggestions
I guess you already tried to create a method like
void doSomething(std::vector<A*>& things)
{
}
and tried do pass
std::vector<B*> bList = ...;
doSomething(bList);
right?
Why does the compiler complain? Because it would not make sense. Consider that doSomething() tries to do
things.push_back(new C());
This cannot work as "things" is actually a std::vector<B*>. However, if it were std::vector<A*>, push_back would work.
So what can we learn from this? What you're trying only makes sense if you only read from the vector, however, vector is not a read-only container.
A simple wrapper shows a possible solution (the wrapper can be adjusted to your needs, of course). However, I have to point out that the use of virtual methods might lead to performance penalties.
class A {};
class B : public A {};
template <class Base>
class AbstractVectorWrapper
{
public:
virtual size_t size() const = 0;
virtual Base* getElementAt(int index) const = 0;
};
template <class Base, class Derived>
class VectorWrapper : public AbstractVectorWrapper<Base>
{
private:
std::vector<Derived*> m_vector;
public:
explicit VectorWrapper(std::vector<Derived*> const& vector)
: m_vector(vector)
{
}
virtual size_t size() const
{
return m_vector.size();
}
virtual Base* getElementAt(int index) const
{
return m_vector[index];
}
};
void doSomething(AbstractVectorWrapper<A> const& wrapper)
{
for (size_t i=0;i<wrapper.size();i++)
{
A* a = wrapper.getElementAt(i);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<A*> as;
std::vector<B*> bs;
doSomething(VectorWrapper<A,B>(bs));
doSomething(VectorWrapper<A,A>(as));
return 0;
}
Is duck-typing good enough for you? Consider this code
template <class T>
void my_function (std::vector <T*> const &values) {
// Use features of A* here
}
This will fail to compile if you use features that pointers to T do not support. By using features of A I think it should be guaranteed that pointers to B and C will also work as expected. However, it would be possible to call this function with vectors of D *, provided D's interface complies with what my_function tries to do.

pointer to std::vector of arbitrary type (or any other templated class)

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.