Understanding the class shared pointers and its use in inheritance - c++

I am having difficulty understanding the piece of code given below.
class Child1 : public Base1 {
public:
int Func1(char *Var);
}
class Cls_X: public std::enable_shared_from_this<Cls_X> {
public:
void Func2(char *Var_copy);
}
Func2 is called from Func1 as below
int Func1(char * Var){
...
make_shared<Cls_X>(ioc, ctx)->Func2(Varcopy_ptr);
...
}
Questions:
How class Cls_X: public std::enable_shared_from_this<Cls_X> works?
Tried googling but couldn't understand the documentation for this, Can someone explain in simple english?
Are Cls_X and Child1 both derived class of Base1 here?
NOTE:
The tag [boost] is added because the code example is taken from one of the boost libraries. Please check the example to see how shared_from_this is used in the program
Ps 1:- Change the suitable title if possible.

How class Cls_X: public std::enable_shared_from_this<Cls_X> works?
It can work iff the specialization of the template class (here std::enable_shared_from_this<Cls_X>) does not need to receive a type parameter (here Cls_X) that is a complete type.
template <typename T>
struct has_a_member { T mem; };
template <typename T>
struct has_a_pointer { T *ptr; };
struct A : has_a_member<A> // error at this point:
// A is incomplete at this point
// the definition of has_a_member<A> cannot be instantiated
{
};
struct B : has_a_pointer<B> // OK, B is incomplete
// still has_a_pointer<B> can be instantiated
{
};
And enable_shared_from_this is designed to work in that case, by expecting an incomplete type.

Related

How to interpret A<B<T>>* as A<C<T>>* where B : public C<T>?

Consider a file main.cc with the following code:
template<typename Commodity>
class Shop
{
public:
Shop(){}
~Shop(){}
};
template<typename FuelType>
class Car
{
public:
Car(){}
virtual ~Car(){}
};
template<typename FuelType>
class Volkswagen : public Car<FuelType>
{
public:
Volkswagen(){}
~Volkswagen(){}
};
int main()
{
// this is fine...
Car<int>* myCar = new Volkswagen<int>();
delete myCar;
// ...but this isn't
Shop<Car<int>>* myCarShop = new Shop<Volkswagen<int>>();
return 0;
}
When I try to compile, I get an error:
cannot convert 'Shop<Volkswagen<int> >*' to 'Shop<Car<int> >*' in initialization...'
Now, I understand why I get this error. It's because Shop<Volkswagen<T>> in general does not have to inherit from Shop<Car<T>>.
My question is: How can I implement a structure like this? Is there a better way with classes and templates or should I, when I'm absolutely certain that Shop<Volkswagen<T>> always is a Shop<Car<T>>, attempt to explitly cast the pointer?
Edit 1: One solution could be to add a class
template<typename FuelType>
class VolkswagenShop : public Shop<Volkswagen<FuelType>>, public virtual Shop<Car<FuelType>>
{
public:
VolkswagenShop(){}
~VolkswagenShop(){}
};
and then write
Shop<Car<int>>* myCarShop = new VolkswagenShop<int>();
This compiles, but the structure has gotten complicated to a point where I, with my very limited c++ ability, am not sure if this won't cause any problems.
So, risking being too vague, will the above solution cause any obvious problems?
Template instantiation is not inheritance! foo<A> and foo<B> are two distinct and unrelated types. If you want all Shop<CARTYPE<T>> to inherit from Shop<Car<T>> then you can do that.
If it is ok to change the declaration of Shop to take 2 template parameters (and if you are not scared of template template parameters) you can do this:
template<typename FuelType>
class Car
{
public:
Car(){}
virtual ~Car(){}
};
template<typename FuelType>
class Volkswagen : public Car<FuelType>
{
public:
Volkswagen(){}
~Volkswagen(){}
};
template <template<class> class CarType,typename Commodity>
class Shop : public Shop<Car,Commodity>
{
public:
using Car_t = CarType<Commodity>;
Shop(){}
virtual ~Shop(){}
};
template <typename Commodity>
class Shop<Car,Commodity> {
virtual ~Shop(){}
};
int main()
{
// this is fine...
Car<int>* myCar = new Volkswagen<int>();
delete myCar;
// this also
Shop<Car,int>* myCarShop = new Shop<Volkswagen,int>();
delete myCarShop;
return 0;
}
However, template specialization is also not inheritance! You will need to repeat all methods in the general template and in the template <typename Commodity> class Shop<Car,Commodity> {}; specialization. To avoid code duplication you could write a ShopBase class that is not a template and provides the interface you want to use polymorphically on all shops.
PS: Mixing compile time and runtime polymorphis is possible, but I would reconsider what you really need. Taking a look at CRTP might give you some inspiration.

C++ Verify template type

Sorry for my poor english I'll try to do my best.
I want to design an interface that should be used like this:
class MyObject : public IMyInterface<MyObject>
{
// ...
};
The interface could look like this:
template <class _TMyObject>
class IMyInterface
{
virtual _TMyObject* Get() = 0;
};
What i'm looking after, is a way to verify, at compile time, that the interface is used as intended.
How can I test if _TMyObject "is-a" IMyInterface<_TMyObject>? Inside the interface definition, with a static_assert for example.
Thanks for any help :).
Have a nice day!
You can't put static_assert inside the class itself, because D is an incomplete type, but you can put it in the destructor (or constructor, but there can be many constructors):
template<class D>
struct B
{
~B()
{
static_assert(std::is_base_of_v<B, D>);
};
};
struct Not_E {};
struct D : B<D> { };
struct E : B<Not_E> { };
void foo()
{
D d; // OK
E e; // Fails
}
Addition. Note that this solution is not a complete protection against incorrect usage of CRTP. Please refer to Some Programmer Dude's answer for a nice example of error that can't be caught by it.
Since C++11 there are many type property traits that could be used to do checks at compile-time.
For example std::is_base_of which in your case could be used like perhaps
template<typename TChild>
struct IMyInterface
{
static_assert(std::is_base_of<IMyInterface, TChild>::value, "Derived class not derived from IMyInterface");
// ...
};
Note: The exact code shown above will not work directly, but rather show the principle.
Of course, that do allow something like
class MyFirstClass : public IMyInterface<MyFirstClass>
{
// ...
};
// Note wrong class in template
// vvvvvvvvvvvv
class MySecondClass : public IMyInterface<MyFirstClass>
{
// ...
};
So to answer your question if it's possible for such a check: Not really the way you want. Even using other traits and meta-programming, you can never guarantee that the template argument for the interface class is "correct" when used in the CRTP.
The only way I can see it work is by using down-casting at run-time with dynamic_cast, something like dynamic_cast<TChild*>(this) != nullptr in the interface class.

static_pointer_cast through inheritance and template

I am having trouble finding a fix for the following error, thrown when compiling a std::static_pointer_cast<>():
error: invalid static_cast from type ecse::EventSubscriptionManager<ecse::BaseEvent>* to type ecse::EventSubscriptionManager<TestEvent>*
I have the following hierarchy. In the end they will be filled with POD type members and will most likely become structs.
class BaseEvent {};
template <class E>
class Event : public BaseEvent, public Type<E> {};
class TestEvent : public Event<TestEvent> {};
I am currently working on the Subscribe function part of the EventManager, however when compiling I am receiving the error posted above. Note: E::ID() is defined in the class as Type and is used for identifying the class type.
template <class E>
class EventSubscriptionManager
{
public:
void Subscribe(std::function<void(E)> fptr);
private:
std::function<void(E)> event_function_;
};
class EventManager
{
public:
template <class E>
void Subscribe(std::function<void(E)> fptr)
{
std::shared_ptr<EventSubscriptionManager<E>> sub_manager_ptr;
auto sub_manager_iterator = sub_managers_.find(E::ID());
if(sub_manager_iterator == sub_managers_.end())
{
sub_manager_ptr = std::make_shared<EventSubscriptionManager<E>>();
}
else
{
sub_manager_ptr = std::static_pointer_cast<EventSubscriptionManager<E>>(sub_manager_iterator->second);
}
// Continue function...
}
private:
std::unordered_map<std::size_t, std::shared_ptr<EventSubscriptionManager<BaseEvent>>> sub_managers_;
}
I believe that the issue is that between the TestEvent and the BaseEvent there is the Event<E> class with the template, with TestEvent inheriting Event<TestEvent> instead of BaseEvent. Is this true? If so, how can I set up my hierarchy to allow for this type of casting?
If that is not the case, what is the issue with the above static cast?
I can tell you why it does not compile. This is because
EventSubscriptionManager<E>
is unrelated to
EventSubscriptionManager<BaseEvent>
So, according to point 1.) on the reference page,
static_cast<EventSubscriptionManager<E>*>((EventSubscriptionManager<BaseEvent>*)nullptr)
is ill-formed.
However, without knowing the background I can't tell what to do as a workaround.
Just: you have to relate the two classes, or choose a completely new design.
In order to do so, here is a minimal example why it fails which might be helpful:
struct Base {};
struct Derived : Base {};
template<typename T>
struct Foo {};
int main()
{
static_cast<Foo<Derived>*>((Foo<Base>*)nullptr);
}
You can try to improve on that.
In C++, there is no covariance or contravariance, there is no relationship between T<Base> and T<Sub>, even if there is one between Base and Sub.
You either need to build a common ancestor of different EventSubscriptionManager instances (e.g: EventSubscriptionManagerBase), and use that, or provide a converting constructor.

How to obtain similar result as virtual function template c++

Here's my issue, I'm trying to create a base class which can get a reference to a queue member in a derived class. I have two template functions in my base class :
class Base
{
template<TYPE type>
virtual void foo(std::queue<TYPE>*& typeQueue) //I know virtual isn't allowed
{
//do nothing as it's general case
}
template<typename TYPE>
void bar(TYPE type)
{
std::queue<TYPE>* typeQueue;
foo(typeQueue);
//... do some stuff with type
}
}
and a derived class which would theoretically be able to specialize the function foo for any types
class Derived : public Base
{
public:
template<>
void foo<int>(std::queue<int>*& m_integerQueue)
{
integerQueue= &m_integerQueue;
}
template<>
void foo<double>(std::queue<double>*& doubleQueue)
{
doubleQueue = &m_doubleQueue;
}
private:
std::queue<int> m_integerQueue;
std::queue<double> m_doubleQueue;
}
code above is more of about an ideology then a code to take word for word, I'd like the function bar to call the according function foo in derived class based on the type specified when bar is called. Of course this solution isn't working and the problem here is that we can't make template functions virtual.
I'm not sure if it's an error of design, but that's the general idea and I couldn't find an appropriate solution anywhere so I posted my own question here.
EDITED to make my problem clear

class containing a generic type of a child

Is there any possible way that a generic type can be used to contain a child of a base class.
From the assignment given to me, I am to create something similar to the following in structure.
template <class T>
class Fruit {
private:
int count;
int location_id;
T type;
public:
virtual void displayInfo();
};
class Apple : private Fruit<Apple> {
private:
int variety;
public:
void displayInfo() {
printf("Location %i has %i of %s in stock", location_id, count, variety);
}
};
Fruit<Apple> appleinventory[SIZE];
Basically, I think you can't have a template generic type be the same as a derived class. Am I wrong? Is there something similar that would possibly work?
Update:
For the assignment, I believe we are to use inheritance to show use of virtual functions. I've updated the code above. I think this would work, but does NOT need templates to be successful. We have not covered any advanced, redundant inheritance methods in class.
This is perfectly fine, in principle.
Read up about Curiously Recurring Template Pattern (CRTP) for more info on usage of derived class as the instantiating type in a class template that is its base, esp the example about static polymorphism which should look 'curiously' familiar.
template <class Derived> struct Base
{
void interface()
{
// ...
static_cast<Derived*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
Derived::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
Ignoring questions of why you want to do this....you can get some of the way by doing this following:
template <class T> class Fruit
{
private:
int count;
int location_id;
T* type;
};
class Apple : private Fruit<Apple>
{
private:
int seeds;
bool red;
};
Fruit<Apple> appleinventory[SIZE];
Note the T* type is now a pointer to Apple rather than an instance of Apple.