I have a base class and its derived class with pointers to forward declared classes:
class BaseParam;
template <class S = BaseParam> class Base;
class BaseParam {
private:
std::unique_ptr<Base<>> ptr;
public:
virtual const Base<>& get_ptr() const {return *ptr;}
};
And similarly for its derived class
class DerivedParam;
template <class S = DerivedParam> class Derived;
class DerivedParam : public BaseParam {
private:
std::unique_ptr<Derived<>> ptr;
public:
const Derived<>& get_ptr() const override {return *ptr;} // <---- Here we'll have trouble
};
The above mentioned class templates are also intertwined with the Param versions, here's the prototype:
template <class S>
class Base {
private:
std::unique_ptr<S> ptr;
// ...
public:
// ...
const S& get_ptr() const { return *ptr; }
};
template <class S>
class Derived : public Base<S> {
};
So that Derived = Derived<DerivedParam> inherits from Base<DerivedParam> But in order to make the return marked with <-- above covariant, we would need Derived to inherit from Base = Base<BaseParam>. How does one do this in a clean fashion? I cannot add an extra inheritance say like
template <class S>
class Derived: public Base<S>, public virtual Base<>
Cause Base and Base<DerivedParam> will hold two different pointers to BaseParam and to DerivedParam. Since a pointer to DerivedParam decays to one to BaseParam there should be a solution where the base class holds only one pointer.
So what I am asking is if there is some functorial way of defining class inheritance for class templates.
Related
How do I ensure my derived class implements at least one of two chosen methods in the base class?
class base {
public:
virtual int sample()=0;
virtual Eigen::VectorXf sample()=0;
};
class Derived : Base {
int sample() override {return 1;}
}
This code returns an error, as the sample method is not implemented with the VectorXf return type. However, my intention is that only one of these need to be implemented. The only reason they are seperate in the base class is that they have different return type. How can I do this in C++?
Overloading by return type is not possible. You may use std::variant instead:
#include <variant>
class Base {
public:
virtual std::variant<int, Eigen::VectorXf> sample()=0;
};
class Derived : public Base {
std::variant<int, Eigen::VectorXf> sample() override {return 1;}
};
If one is restricted to C++11, then there are many alternatives.
Implement and use something like variant: a class that has a enumerator selecting between two active types, and a union to contain these types.
Use Boost variant.
std::pair
Implement a hierarchy of classes (a simplification of std::any), and return on the right pointer to object:
class AbstractBase {
public:
virtual ~AbstractBase() = 0;
template <class T>
const T* get() const;
};
template <class T>
class ValueWrapper : public AbstractBase {
public:
ValueWrapper(const T& value) : m_value(value) {}
const T & getValue() const { return m_value; }
private:
T m_value;
};
template <class T>
inline const T * AbstractBase::get() const {
auto child = dynamic_cast<ValueWrapper<T> const*>(this);
return child ? &child->getValue() : nullptr;
}
class Base {
public:
virtual std::unique_ptr<AbstractBase> sample()=0;
};
The question is, why would you need this?
I'm trying to make a tree structure to manage data whose structure can change depending on the type.
Here is what I did for the base object
//Type1.. are the types of the leaves having Base as common parent
enum class EnumBase{Type1,Type2,Type3};
class Base {
protected:
EnumBase const _type;
Base(EnumBase typ) : _type(typ){}
public:
virtual ~Base() = default;
Base() = delete;
EnumBase getType() const {return _type;}
};
while this is to create and get different derived
template<class Leaf>
class Controller {
private:
std::shared_ptr<Leaf> _pt;
public:
template<class Derived>
void create() {
_pt = std::make_shared<Derived>();
return;
}
template<class Derived>
Derived & get(){
auto pt = std::dynamic_pointer_cast<Derived>(_pt);
if(!pt){
throw; //bad cast
}
return *pt;
}
};
The second level of the tree goes like:
enum class Type1Types{T1,T2};
class Type1 : public Base {
protected:
Type1Types const _type;
Type1(Type1Types typ) : Base(EnumBase::Type1), _type(typ){}
public:
virtual ~Type1() = default;
Type1() = delete;
Type1Types getType() const {return _type;}
};
class Type2; //...the same with EnumBase::Type2 and Type2Types
class Type3; //...the same with EnumBase::Type3 and Type3Types
with final implementations which may possibly include Controller for another data type:
class T1 : public Type1 {
public:
T1() : Type1(Type1Types::T1) {}
//... data of T1
};
class T2 : public Type1 {
public:
Controller<Type2> objType2;
//... other data for T2
};
The idea behind all this is that I can write:
int main(){
Controller<Type1> obj;
obj.create<T2>();
obj.get<T2>().objType2.create<somethinginType2>();
//...
}
Probably such pattern is overcomplicated (any comment and suggestion is welcomed) but a pattern exists and I believe that it is possible with some template magic and some recursion to write a general templated version of a leaf (Type1, Type2,..) so that I don't have to copy/paste the code and only change the type of the enum for the children (Type1Types) and the type for itself (EnumBase::Type1).
I was thinking of some structure like
template<class Me, class... Parents>
struct MagicStructure{
//some typedef
//my type
}
Any idea?
I'm trying to create the following flow:
Having a 'Base' class, with no params or functionality, just so i can hold
Base pointers in a method.
Its derived class, is a template, which implements operator() on given template argument object type.
I'm trying, by using a pointer to base class, call the derived class operator(), in run-time.
I've tried implementing it using CRTP
(https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)
But that doesn't seem to work the-other-way-around - when the derived class is a class template.
Here is my code:
class Base {};
template<typename Ref_Obj, typename Obj_Type>
class Derived : public Base {
private:
typedef bool (Ref_Obj::*Func_p)(Obj_Type) const;
Func_p m_func;
const Ref_Obj& m_db;
public:
Derived<Ref_Obj, Obj_Type>(const Ref_Obj& db, Func_p func): m_db(base), m_func(filter) {}
inline bool operator()(const Obj_Type& obj) const {
return (m_db.*m_func)(obj);
}
}
Now, usage is in another class template, that contains vector of Base class pointers, as follows, and have its own operator() :
template<typename Obj_Type2> /* Upon usage, Obj_Type2 is the same as Obj_Type, this is just to differ the two in the code here */
class BlaBla {
private:
std::vector<const Base *> m_vec;
public:
/* relevant constructors ... */
inline bool operator()(const Obj_Type2 &obj) const {
for(std::vector<const Base *>::const_iterator it = m_vec.begin(); it != m_vec.end(); ++it) {
/*** This is the problematic line V ***/
if( (*it).operator()(obj) ) { /* DO SOMETHING */ }
}
}
Of course the compiler is complaining that there is no matching function to call for in the problematic line that is marked in the code below, but i can't figure out a way to do the relevant call.
1st Solution that came to mind, is to create a virtual operator()(...), with a specific object type e.g. virtual operator()(const uint32_t &obj) in Base class, which works, but my intention is that operator()(...) will receive a variety of object types, and stating a virtual method for each of them is not elegant and seems to break all the template concept i want to implement here.
2nd Solution that came to mind, is somehow passing Ref_Obj and Obj_Type typenames to Base class, to be used in sort of interface method, that will use static_cast to call the appropriate Derived operator (As in CRTP) - But that doesn't seem to work because Derived class is a class template, and also BlaBla class doesn't directly know Ref_Obj typename.
Is there any other way to make the appropriate call to Deriver operator()
There is no clear clean way to do this. The fundamental problem is that there is no such thing as a virtual template method.
The cleanest way I can think of doing this that implements complete type erasure is with a dynamic cast, and a virtual method:
class Base {
public:
virtual bool operator()(const Base &) const=0;
};
template<typename Ref_Obj, typename Obj_Type>
class Derived : public Base {
private:
typedef bool (Ref_Obj::*Func_p)(Obj_Type) const;
Func_p m_func;
const Ref_Obj& m_db;
public:
Derived<Ref_Obj, Obj_Type>(const Ref_Obj& db, Func_p func): m_db(base), m_func(filter) {}
inline bool operator()(const Base& obj) const override {
const Obj_Type *derived_obj=dynamic_cast<const Obj_Type *>(&obj);
if (!derived_obj)
{
throw; // Or maybe return false, or something...
}
return (m_db.*m_func)(*derived_obj);
}
};
Obj_Type must also be derived from Base. This gets the job done at runtime, but there is no compile-time type-checking.
The other approach is to bite the bullet, and forego 100% type erasure:
template<typename Obj_Type>
class Base {
public:
virtual bool operator()(const Obj_Type &) const=0;
};
template<typename Ref_Obj, typename Obj_Type>
class Derived : public Base<Obj_Type> {
private:
typedef bool (Ref_Obj::*Func_p)(Obj_Type) const;
Func_p m_func;
const Ref_Obj& m_db;
public:
Derived<Ref_Obj, Obj_Type>(const Ref_Obj& db, Func_p func): m_db(base), m_func(filter) {}
inline bool operator()(const Obj_Type& obj) const override {
return (m_db.*m_func)(obj);
}
};
So, you can still abstract away operator() on some object to its pure interface, and define the details in the subclass.
Or, another alternative would be a combination of the two:
class SuperBase {
public:
virtual bool operator()(const Base &) const=0;
};
template<typename Obj_Type>
class Base : public SuperBase {
public:
virtual bool operator()(const Obj_Type &) const=0;
bool operator()(const Base &obj) const override
{
// Do the dynamic cast check, and forward it to the other
// operator().
}
};
Consider the following code:
class Base
{
public:
virtual void* allocate(){ return nullptr; }
};
template <class T> class BaseTemplate : public Base
{
public:
void* allocate() override { return new T(); }
};
class IntSpecialization : public BaseTemplate<int>
{
};
Base GetSpecialization(const int&){ return IntSpecialization(); }
The goal is to be able to use template to implement specializations, but still allow users to work using the base class interface, such as:
int a;
auto s = GetSpecialization(a);
auto p = s.allocate();
The above code does not work; s.allocate() always return nullptr for obvious reasons.
I absolutely need the GetSpecialization function to return the Base non-template class, so how do I go about this?
The Base class virtual method cannot be pure, because otherwise it becomes abstract and it will fail the compilation at GetSpecialization.
What is the best approach to solve this pattern? Using C++11?
Thanks!
Base GetSpecialization(const int&){ return IntSpecialization(); }
You're slicing the IntSpecialization object above. To make your code work, GetSpecialization must return a Base *, or a Base&. For instance, the following will work as you intended it to:
std::unique_ptr<Base> GetSpecialization(const int&)
{
return std::unique_ptr<Base>(new IntSpecialization());
}
Live demo
For the above code to work, you'll need to add a virtual destructor to Base.
class Base
{
public:
virtual void* allocate(){ return nullptr; }
virtual ~Base() = default;
};
Otherwise, when the unique_ptr goes out of scope it'll call delete ptr;, where the type of ptr is Base *, and polymorphic deletion of a derived class object through a base class pointer is undefined behavior unless the base class destructor is virtual.
Just make Base have pointer to BaseTemplate:
class BaseInterface {
public:
virtual void* allocate() = 0;
}
class Base
{
std::unique_ptr<BaseInterface> interface;
public:
Base( BaseInterface *i ) : interface( i ) {}
void* allocate(){ return interface->allocate(); }
};
template <class T> class BaseTemplate : public BaseInterface
{
public:
void* allocate() override { return new T(); }
};
class IntSpecialization : public BaseTemplate<int>
{
};
Base GetSpecialization(const int&){ return Base( new IntSpecialization ); }
Less verbose solution is to use std::function and lambda
class Base
{
public:
typedef std::function<void *()> creator;
Base( const creator &c ) : cr( c ) {}
void *allocate() { return cr(); }
private:
creator cr;
};
template<class T>
Base GetSpecialization( const T & ) { return Base( []() { return new T; } ); }
What I want to doe is a simple conditional inheritance in the Foo class
so depending on how it's instanciated (see usage)
class BaseType
{
protected:
m_valueX;
public: BaseType(int param = 0):m_valueX(param){}
~ BaseType(){}
}
...
class Type1 : public BaseType
{
public: Type1():BaseType(1){}
~Type1(){}
}
...
class Type2 : public BaseType
{
public: Type2(): BaseType(2){}
~Type1(){}
}
...
template<typename Base>
class Foo: public Base
{
public:
Foo(){}
~Foo();
void dothis();
}
...........
in cpp file
template<typname Base>
Foo<Base>::Foo():Base()
{
}
Foo::~Foo(){}
void Foo::dothis(){}
usage:
Foo* fooptr1 = new Foo<Type1>();<== error use of class template requires template argument list
Foo* fooptr2 = new Foo<Type2>();>();<== error use of class template requires template argument list
Thank you!
Foo is a template, not a class. The common class type for all Foo<T> is Base, so you can say:
Base * p1 = new Foo<Type1>;
Base * p2 = new Foo<Type2>;