static_pointer_cast through inheritance and template - c++

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.

Related

Create a templated variable within a templated class of a different type

I'm not sure what I am asking for is possible.
I have a templated class called Controller. This is a variadic template class which takes multiple classes and can set their values as such.
Controller<ClassA,ClassB,ClassC>* myController = new Controller<ClassA,ClassB,ClassC>(*a,*b,*c);
myController->setValues(32);
This takes a bunch of different classes together and allows me to to set their values at the same time. setValues is a templated function which allows any type to be passed in. However, right now I am trying to modify my class so that I can set a value within the controller itself for easy retrieval. However this is the part that is proving difficult.
template<typename...Classes>
class Controller
{
public:
Controller(Classes&...objects) : objects(objects...){}
Controller(std::tuple<Classes&...> tup) : objects(tup){}
template<typename T>
void setValues(T value)
{
std::apply([&](auto&...x) { x.updateValue(value),...);}, objects); //calls the updateValue function for each class
}
private:
std::tuple<Classes&...> objects;
};
I want to add the following as a private variable T controllerValue; However, I know that I cannot simply declare T because we cannot define member templates and the compiler has no idea what to expect. Which then I tried to create a private struct:
template<typename T>
struct ControllerValue { T value; };
However, I cannot define a struct underneath that, because the same problem occurs. The compiler has no idea what type ControllerValue is. What I would like is something like this:
template<typename...Classes>
class Controller
{
public:
Controller(Classes&...objects) : objects(objects...){}
Controller(std::tuple<Classes&...> tup) : objects(tup){}
template<typename T>
void setValues(T value)
{
thisValue.value = value;
std::apply([&](auto&...x) { x.updateValue(value),...);}, objects); //calls the updateValue function for each class
}
template<typename T>
T getValue() const { return thisValue.value }
private:
std::tuple<Classes&...> objects;
template<typename T>
struct ControllerValue { T value; };
ControllerValue thisValue;
};
This will not compile at all for the same reason that the compiler has no idea what type ControllerValue should be. And this is where I am stuck. Is this even possible to do? If not, what is another way that I can make this work?
To clear up confusion, the use case would be something like this:
Controller<ClassA,ClassB,ClassC>* myController = new Controller<ClassA,ClassB,ClassC>(*a,*b,*c);
myController->setValues(32);
int commonValue = myController->getValue();
or
Controller<ClassA,ClassB,ClassC>* myController = new Controller<ClassA,ClassB,ClassC>(*a,*b,*c);
myController->setValues(32.3);
double commonValue = myController->getValue();
I think solving this exact problem is impossible in C++ (and still very cumbersome in languages with runtime generics). You can very easily create a polymorphic class that can only store any value:
class PolymorphicBase
{
public:
virtual ~PolymorphicBase() = default;
};
template <class T>
class PolymorphicObject : public PolymorphicBase
{
T value;
public:
PolymorphicObject(T value) : value(std::move(value))
{
}
};
A member of std::unique_ptr<PolymorphicBase> can sufficiently store any value, but how would such a value be retrieved? Probably the easiest is to expose the reference to PolymorphicBase and use dynamic type checks to see if the type is compatible with something you know, but what if you need the code to work for any type?
This is what lambdas with auto parameters are useful for. However, you would have to be able to pass such a lambda to a method on PolymorphicBase and implement that method in PolymorphicObject. This is impossible, since you cannot override a method template (it needs to be a template to accept a lambda) – that's where the compile-time and runtime parts of C++ clash. And there is simply no type in C++ that represents a function accepting any parameter (and knowing its type), which is a template by itself.
You can partially solve this by making the type of the lambda known to PolymorphicBase:
template <class Retriever>
class PolymorphicBase
{
public:
virtual void retrieve(Retriever func) = 0;
virtual ~PolymorphicBase() = default;
};
template <class Retriever, class T>
class PolymorphicObject : public PolymorphicBase<Retriever>
{
T value;
public:
PolymorphicObject(T value) : value(std::move(value))
{
}
void retrieve(Retriever func) override
{
func(value);
}
};
auto lambda = [](auto arg)
{
std::cout << arg << std::endl;
};
PolymorphicObject<decltype(lambda), int> obj(6);
PolymorphicBase<decltype(lambda)> &ptr = obj;
ptr.retrieve(lambda);
This is useful if you ever have only a single way to retrieve the value.
I don't think this is needed in most cases anyway. Usually you use a fixed set of types as the values, so you can use a variant there, or they all implement a common interface, or (as you've pointed out in the comments) you actually meant to move the type parameter from the method to the class (which allows you to check that all the types actually support the value earlier than originally).
However, I agree that in languages with generics/templates it is somewhat hard to have a method that can actually choose its result type in a generic fashion, without being controlled by outside parameters.

Understanding the class shared pointers and its use in inheritance

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.

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.

Call right template function via base class pointer

I think I'm already close to the solution but am missing the final step.
I want to call a templated member function where I only have a pointer
to the base class and the type is already predefined, so should not
depend on the actual argument type.
This is what I have:
template <typename T> class TTemplateTest;
class CTemplateTest
{
public :
CTemplateTest(){};
template <typename T> double Process(T atValue)
{
return static_cast<TTemplateTest<T>* >(this)->Process(atValue);
}
};
//------------------------------
template <class T>
class TTemplateTest:public CTemplateTest
{
public :
TTemplateTest() : CTemplateTest(){};
virtual double Process(T atNewValue) {return atNewValue;};
};
//------------------------------
template <class T>
class TTemplateTestInt:public TTemplateTest<T>
{
public :
TTemplateTestInt(){};
virtual double Process(T atNewValue);
};
//------------------------------
template <class T> double TTemplateTestInt<T>::Process(T atNewValue)
{
return atNewValue;
}
CTemplateTest* pTTest = new TTemplateTestInt<int>();
// application code
double d = 5.5;
double r;
r = pTTest->Process(d);
I would like to process the argument as integer in this example,
no matter what type the argument is. It calls the right function
but the value is garbage as the double is interpreted as integer
instead of being converted.
I have looked at other questions (and other sites) but couldn't
find a match or solution, e.g.
calling a template function of a derived class
The solution probably is CRTP but I couldn't figure out how
to use it. The application code should stay like this, the
classes definitions can change. The reason for this code is
that it is generated and used in runtime from some xml
configuration file. So the type is not really known at the
function call.
It would probably help if I could use the defined type, like:
template <typename T> double Process(T atValue)
{
return static_cast<TTemplateTest<T>* >(this)->Process((this::type)atValue);
}
Or prevent the automatic creation of the function using double
so the argument is converted to integer as it would happen on
a non templated function.
Thanks for any help.
Edit: Next solution
Does this look valid? It doesn't need casting and we only need a handful of different basic types for the template so there won't be many redirector functions. And it should still be efficient (without typeinfo and such).
I'm also posting it in case somebody else has a similar problem.
class CTemplateTest
{
public :
CTemplateTest(){};
virtual inline double Process(double adValue)=0;
virtual inline double Process(int aiValue)=0;
};
//------------------------------
template <class T>
class TTemplateTest:public CTemplateTest
{
public :
TTemplateTest() : CTemplateTest(){};
virtual inline double Process(double adValue) {
return ProcessImp((T)adValue);
}
virtual inline double Process(int aiValue) {
return ProcessImpl((T)aiValue);
}
virtual double ProcessImpl(T atNewValue)=0;
};
//------------------------------
template <class T>
class CTemplateTestInt:public TTemplateTest<T>
{
public :
CTemplateTestInt(){};
virtual double ProcessImpl(T atNewValue) {return atNewValue;};
};
This then gives the desired result with
CTemplateTest* pTTest = new TTemplateTestInt<int>();
// application code
double d = 5.5;
double r;
r = pTTest->Process(d);
// -> r = 5
Thanks
Your code looks fairly confusing, both in terms of naming and the logic. I don't know what you want to do, but I can explain why your code will lead to strange behavior, which also indicates there are some fondamental design flaw in your code.
To be simplified, your code has something similar to this:
class A {};
class B : public A {};
class C : public A {};
int main () {
A *a_ptr = new B {};
C *c_ptr = static_cast<C*>(a_ptr);
}
There is no reinterpret_cast, but this code still breaks the type system and will lead to undefined behavior. Because B has nothing to do with C, even if they both derive from A.
Back to your code, in class CTemplateTest, function
template <typename T> double Process(T atValue)
{
return static_cast<TTemplateTest<T>* >(this)->Process(atValue);
}
will obtain type T by template argument deduction, not from any predefined type. Thus pTTest->Process(d) will deduce type T to be double and in that function, static_cast the this pointer to an irrelevant pointer TTemplateTest<double>*. But this pointer is indeed a TTemplateTest<int>*, these two classes have no relation except both deriving from CTemplateTest. So it's just the simplified case.
I don't know how to fix this code...
A few observations:
1) your base class has no virtual function, but your derived classes each have unique, unrelated virtual functions. They do not override anything so are kind of pointless being virtual.
2) The base class doesn't know what type the derived type was instantiated with. When CTemplateTest::Process is called, that T is the argument deduced for the function call, and is unrelated to the T used for the derived type. You're merely casting the object to the template instantiated with the type you were provided, ignoring the type your object actually is. This accounts for the garbage; it's undefined behavior.
3) There is no such thing as a template virtual function. One or the other; take your pick. That's basically what I think you are trying to simulate. You want the same function to take any type of parameter and have it passed, as that type, to the derived type, who knows how to process it its own templated way. I'm not sure of a satisfying way to accomplish this.
One thought is to pre-determine a fixed set of types you will accept and handle them individually, one virtual function per supported type. You may be able to make this a bit more flexible with a template parameter list and use the compiler to generate the functions, but I haven't thought that approach entirely through. :)

Struct Inheritance Hierarchy - Dynamic down-cast

i have following 2 structs which are defined within a template class and a container, which holds elements of the base class, as follows:
class template<typename T1, typename T2>
class TTestDataObject
{
private:
//base element
struct SDataContainerElement
{
T1* m_sData;
};
//derived element
struct SInvalidDataContainerElement : SDataContainerElement
{
int m_eExpectedErrorCode;
};
//container holding base elements
typedef std::map<T2, SDataContainerElement* > TDataContainer;
TDataContainer sCInvalidData;
public:
typedef TDataContainer::const_iterator TDataConstIterator;
}
I want to implement a method, which can extract information from this container, doing different things depending on which element it has, the base class (SDataContainerElement) or the derived class (SInvalidDataContainerElement) and I implemented it as follows :
template<typename TDataStruct, typename TDataEnum>
int TTestDataObject<T1, T2>::eGetExpectedError(T2 eIndex)
{
TDataConstIterator sElement = sCInvalidData.find(eIndex);
if(dynamic_cast<SInvalidDataContainerElement*>((sElement->second)) == NULL)
return -1;
else
return static_cast<int>(sElement->second->m_eExpectedError);
}
Trying to compile leads to the following error :
E2307 Type'TTestDataObject<BEREICHTYP,eTestDataBereichTyp>::SDataContainerElement' is not a defined class with virtual functions
I don't understand this. Can anybody explain this error to me and show me a solution pls?
Thanks in advance!
As described in FAQ: Why does dynamic_cast only work if a class has at least 1 virtual method? , i need a virtual method, like a virtual destructor, in the base class.
To make this code work, i simply added
virtual ~SDataContainerElement(){};
to the base - struct. Thanks!