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?
Related
I have an enum class Type. If I have a base class and a derived class like this:
template<Type T>
class Templated
{
public:
Type GetType() const
{
return T;
}
};
class DerivedTemplated : public Templated<Type::None>
{
};
Is this better in any way than having this:
class NoTemplate
{
public:
virtual Type GetType() const = 0;
};
class DerivedNoTemplate : public NoTemplate
{
public:
Type GetType() const override { return Type::None; }
};
Using templates is not necessary in this case, but I don't know if I should use them or not. I often store polymorphic collections of the base class, so in the templated case I would have to create an interface:
class ITemplated
{
public:
virtual Type GetType() const = 0;
};
and derive Templated from it. Are there any benefits to the templated one over the pure virtual function?
I think the first makes no sense. Because how would you use this? For example
template<Type T>
int int_of_type(const Templated<T> &bar) {
return hash(bar.get_type());
}
why not just write:
template<Type T>
int int_of_type(const Templated<T> &) {
return hash(T);
}
or
template<Type T>
int int_of_type<T>() {
return hash(T);
}
I see no way the get_type can be used where you couldn't just use T directly. Maybe you need a more complex example to show what you are trying to solve.
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 am using a composite design pattern and I want to clone my objects from my composite class. I tried to make a generic clone method in my component class, but when I try to send the concrete type of my object to the generic (template) method, 'typeof' and 'typeid' returns the abstract class type. So, when I try to use new typeof(object), I see the error
"invalid new-expression of abstract class type 'Component'".
My compiler is MigGW 32 bits.
As I can't know the type of my object, I can't use dynamic_cast.
Am I using typeof/typeid wrongly or should I use other keyword to know the concrete object type?
#include <iostream>
#include <vector>
#include <typeinfo>
class Component
{
public:
template <typename Tdest> typename std::remove_cv<typename std::remove_pointer<Tdest>::type>::type* clone() const
{
typedef typename std::remove_cv<typename std::remove_pointer<Tdest>::type>::type NO_POINTER_NOR_CV;
return new typeof(NO_POINTER_NOR_CV)(*dynamic_cast<const NO_POINTER_NOR_CV*>(this));
}
virtual void manipulateComponents() = 0;
virtual void add(Component* comp) = 0;
protected:
std::vector<const Component*> _v;
};
class Leaf : public Component
{
void manipulateComponents() override { return; }
void add(Component* comp) override { return; }
};
class Composite : public Component
{
public:
void manipulateComponents() override
{
for(auto component : _v)
{
std::cout << typeid(component).name() << std::endl; // print PK9Component
component->clone<typeof(component)>();
/* ... */
}
}
void add(Component* comp) override { _v.push_back(comp); }
};
int main(int argc, char* argv[])
{
Component* l = new Leaf();
Component* c = new Composite();
Component* parent = new Composite();
parent->add(l);
parent->add(c);
parent->manipulateComponents();
}
You are not getting the details of the derived type using typeid since you are using it on a pointer. Dereference the pionter in the call to get the name of the derived type.
Change
std::cout << typeid(component).name() << std::endl; // print PK9Component
// PK9Component seems indicate that it is a pointer to a Component.
to
std::cout << typeid(*component).name() << std::endl;
// ^^
If you want a clone method, you have to add a virtual function to return it, as in:
struct A
{
virtual std::unique_ptr<A> clone() const = 0;
A() = default;
A(A const&) = default;
A(A&&) = default;
A& operator=(A&&) = default;
A& operator=(A const&) = default;
virtual ~A() = default;
};
struct B : A
{
std::unique_ptr<A> clone() const override
{
assert(typeid(*this) == typeid(B));
return std::make_unique<B>(*this);
}
};
The assert protects (at run time) against deriving from B w/o overriding the clone() method.
The C++ Committee is working on A polymorphic value-type for C++, but that won't be available for a while.
No amount of typeof magic in your clone method will give you the type of a subclass of a non-templated class. It can give you the type of an instantiated template, but the only possible instantiation of your clone method here is in your base class. Subclassing doesn't redefine template methods.
If you really want to, you can use template methods in subclassing if you're willing to use the "Curiously Recurring Template Pattern". There's a sample clone implementation on Wikipedia, which I'll quote here:
// Base class has a pure virtual function for cloning
class Shape {
public:
virtual ~Shape() {};
virtual Shape *clone() const = 0;
};
// This CRTP class implements clone() for Derived
template <typename Derived>
class Shape_CRTP : public Shape {
public:
virtual Shape *clone() const {
return new Derived(static_cast<Derived const&>(*this));
}
};
// Nice macro which ensures correct CRTP usage
#define Derive_Shape_CRTP(Type) class Type: public Shape_CRTP<Type>
// Every derived class inherits from Shape_CRTP instead of Shape
Derive_Shape_CRTP(Square) {};
Derive_Shape_CRTP(Circle) {};
With CRTP, you may do:
template <typename Derived>
class IClonable
{
public:
virtual ~IClonable() = default;
std::unique_ptr<Derived> clone() const {
return std::unique_ptr<Derived>(cloneImpl());
}
protected:
virtual Derived* cloneImpl() const = 0;
};
template <typename Derived, typename Base>
class Clonable : public Base
{
public:
std::unique_ptr<Derived> clone() const { // Hide Base::clone to return static type.
return std::unique_ptr<Derived>(static_cast<Derived*>(cloneImpl()));
}
protected:
Clonable* cloneImpl() const { return new Derived{static_cast<const Derived&>(*this)}; }
};
And then:
class Component : public IClonable<Component>
{
public:
virtual void manipulateComponents() = 0;
virtual void add(const Component&) = 0;
};
class Leaf : public Clonable<Leaf, Component>
{
public:
void manipulateComponents() override {}
void add(const Component&) override {}
};
class Composite : public Clonable<Composite, Component>
{
public:
void manipulateComponents() override
{
for (const auto* component : _v)
{
auto cloned = component->clone(); // std::unique_ptr<Component>
/* ... */
}
}
void add(const Component& comp) override { _v.push_back(&comp); }
protected:
std::vector<const Component*> _v;
};
With possible usage:
Leaf l;
Composite c;
auto parent = c.clone(); // std::unique_ptr<Composite>
parent->add(l);
parent->add(c);
parent->manipulateComponents();
I have a family of classes, and each subclass needs a map but the keys will have different types, although they both will perform the exact same operations with the map. Also the value on both cases will be string.
So far I have code similar to the example below, my goal is to reuse code, by
having a generic key.
Without using any additional libraries besides STL
class A{
public:
/*
* More code
*/
};
class subA1 : public A{
public:
void insertValue(long id, std::string& value){
if(_theMap.find(id) == _theMap.end())
{
_theMap[id] = value;
}
}
private:
std::map<long,std:string> _theMap;
};
class subA2 : public A{
public:
void insertValue(std::string& id, std::string& value){
if(_theMap.find(id) == _theMap.end())
{
_theMap[id] = value;
}
}
private:
std::map<std::string,std:string> _theMap;
};
Simply make superclass A a template, move both _theMap and insertValue() to it, and use the correct template version in subclasses.
template <typename KeyT>
class A{
public:
void insertValue(KeyT id, std::string& value){
if(_theMap.find(id) == _theMap.end())
{
_theMap[id] = value;
}
}
private:
std::map<KeyT, std:string> _theMap;
};
class subA1 : public A<long> {};
class subA2 : public A<std::string> {};
You can merge subA1 and subA2 into a single template class, eg:
class A{
public:
/*
* More code
*/
};
template <typename KeyType>
class subA : public A {
public:
void insertValue(const KeyType &id, const std::string& value) {
if(_theMap.find(id) == _theMap.end()) {
_theMap.insert(std::make_pair(id, value));
}
}
private:
std::map<KeyType, std:string> _theMap;
};
You can then create typedefs as needed:
typedef subA<long> subA1;
typedef subA<std::string> subA2;
Or, if you need actual derived classes:
class subA1 : public subA<long>
{
...
};
class subA2 : public subA<std::string>
{
...
};
How about writing another small base class, say C<T> which is a template typename T and just includes a map<T, string> and your insert function. Then each new subclass of A will also be a subclass of C as well. So your subA1 will be public A, public C<long> etc.
I have the following template classes,
I need to figure out how to implement a conversion operator between the derived template classes.
template<class T>
class Base
{
public:
Base () { }
template <class U>
operator Base<U>()
{
return Base<U> (v);
}
virtual double getV() = 0;
};
class D1: public Base<D1>
{
public:
D1(int j)
{
i = j;
}
double getV() const { return i; }
template <class U>
operator Base<U>()
{
return Base<U>(getV());
}
private:
int i;
};
class D2: public Base<D2>
{
public:
D2(int j)
{
i2 = j;
}
double getV() const { return i2; }
template <class U>
operator Base<U>()
{
return Base<U>(getV());
}
private:
int i2;
};
How can I achieve the following?
D1 d1(3);
D2 d2 = d1; //conversion from 'D1' to non-scalar type 'D2' requested
if the design itself sound or should I be doing something else?
Please let me know what ur thoughts
In your example, I don't see a reason why CRTP is used.
The specializations of Base all have a virtual member function that is not dependent on the template parameter. Your code suggests this virtual member function can be used to access all data necessary to create an instance of any class derived from a specialization of Base. If we follow this assumption, one could rather think of:
class Base
{
public:
virtual double getV() const = 0;
};
class D1 : public Base
{
int i;
public:
D1(int);
virtual double getV() const { return i; }
};
class D2 : public Base
{
int i;
public:
D2(int);
virtual double getV() const { return i; }
};
This still does not allow conversions. However, it is quite simple to add them here:
class D1 : public Base
{
int i;
public:
D1(int);
D1(Base const& p) : D1(p.getV()) {}
virtual double getV() const { return i; }
};
This conversion should be allowed by D1 and not by Base, because only D1 knows what data is required for it to be constructed.
If CRTP is necessary for things not shown here, you could still use a common base class:
class Common_base
{
public:
virtual double getV() const = 0;
};
template<class T>
class Base : public Common_base
{
};
class D1 : public Base<D1>
{
int i;
public:
D1(int);
D1(Common_base const& p) : D1(p.getV()) {}
virtual double getV() const { return i; }
};
If, for some reason, the CRTP is required for the conversion, you could still use a converting constructor template:
template<class T>
class Base
{
public:
virtual double getV() const = 0; // whyever
};
class D1 : public Base
{
int i;
public:
D1(int);
template<class U>
D1(Base<U> const& p) : D1(p.getV()) {}
virtual double getV() const { return i; }
};
It's hard to tell what you are trying to do but I don't think you can do it as described.
If you really want to have a common interface, you need to declare a common base class that includes all the methods and properties that your code needs, and have both classes derive from that. You can then always cast to the base class.
This seems ideal in fact. Especially since you can always use virtual methods to customize behavior in the base class if needed.
If that doesn't work within your current task, perhaps you should talk more about why you need this.
You either write a constructor for D2 that takes a const D1& or you write a conversion operator in D1 that returns a D2. You have to decide what it means to do this conversion and implement the conversion appropriately.
You can add a constructor in your derived classes that takes a Base template :
template <class U>
D2(const Base<U> &other)
{
i2 = other.getV();
}
But not sure if it will fit your needs.