Problem trying to cast generically a derived templated class [duplicate] - c++

class A
{
friend void foo();
virtual void print_Var() const{};
};// does not contain variable Var;
template<class T>
class B : public A
{
T Var;
public:
B(T x):Var(x){}
void print_Var() const override
{
std::cout<<Var<<std::endl;
}
};
void foo()
{
std::array<std::unique_ptr<A>, 3> Arr = {
std::make_unique<B<int>>(100),
std::make_unique<B<int>>(20),
std::make_unique<B<std::string>>("Hello Stackoverflow")
};
std::shuffle(Arr.begin(), Arr.end(), std::mt19937(std::random_device()())); // 3rd parameter generated by Clang-Tidy
for (auto &i: Arr)
{
i->print_Var(); // OK
// auto z = i->Var // no member named Var in A
// obviously base class does not contain such variable
// if (i->Var==20) {/* do something*/}
// if (i->Var=="Hello Stackoverflow") {/* do something*/}
}
}
Explanation:
I want to iterate over array of pointers to A, which is filled with pointers to classes derived from A, and depending on what type is variable Var, do some if( ) statement.
Problem is that i cannot access Var, cause its not member of base class. However, it's possible to cout those values by, for example, overloaded function returning void. Could i write function in A class that returns templated type? like:
class A
{
<class T> GetVar()
}
Besides, I feel like I'm dealing with this problem in totally improper way. Can i mix templates and inheritance like that? If not, how should it be designed?

You have a few choices. I'll explain my preferred solution first.
1. Use dynamic dispatch
If you have an array of a base class type, why do you even want to do stuff with Var? That variable is specific to the child class. If you have a A somewhere, you shouldn't even care what B has or hasn't at that place.
Operations on the typed variable should be encapsulated in virtual function in the base class. If you want to do condition and stuff, maybe you could encapsulate that condition into a virtual function that returns a boolean.
2a. Drop the base class and use variant
Sometimes, you know in advance the amount of types that will go into that list. Using a variant and drop the base class is a good solution that may apply to your case.
Let's say you only have int, double and std::string:
using poly = std::variant<B<int>, B<double>, B<std::string>>;
std::array<poly, 3> arr;
arr[0] = B<int>{};
arr[1] = B<double>{};
arr[2] = B<std::string>{};
// arr[2] = B<widget>{}; // error, not in the variant type
std::visit(
[](auto& b) {
using T = std::decay_t<decltype(b)>;
if constexpr (std::is_same_v<B<int>, T>) {
b.Var = 2; // yay!
}
},
arr[0]
);
2b. Drop the base class and use generic functions
Drop the base class entirely, and template your functions that do operation on them. You can move all your function into an interface or many std::function. Operate on that instead of the function directly.
Here's an example of what I meant:
template<typename T>
void useA(T const& a) {
a.Var = 34; // Yay, direct access!
}
struct B {
std::function<void()> useA;
};
void createBWithInt {
A<int> a;
B b;
b.useA = [a]{
useA(a);
};
};
This is fine for cases where you only has a few operation. But it can quickly lead to code bloat if you have a lot of operation or if you have many types of std::function.
3. Use a visitor
You could create a visitor that dispatch to the right type.
This solution would be much close to what you except, but is quite combersome and can break easily when adding cases.
Something like this:
struct B_Details {
protected:
struct Visitor {
virtual accept(int) = 0;
virtual void accept(double) = 0;
virtual void accept(std::string) = 0;
virtual void accept(some_type) = 0;
};
template<typename T>
struct VisitorImpl : Visitor, T {
void accept(int value) override {
T::operator()(value);
}
void accept(double) override {
T::operator()(value);
}
void accept(std::string) override {
T::operator()(value);
}
void accept(some_type) override {
T::operator()(value);
}
};
};
template<typename T>
struct B : private B_Details {
template<typename F>
void visit(F f) {
dispatch_visitor(VisitorImpl<F>{f});
}
private:
virtual void dispatch_visitor(Visitor const&) = 0;
};
// later
B* b = ...;
b->visit([](auto const& Var) {
// Var is the right type here
});
Then of course, you have to implement the dispatch_visitor for each child class.
4. Use std::any
This is litteraly returning the variable with type erasure. You cannot do any operation on it without casting it back:
class A {
std::any GetVar()
};
I personnaly don't like this solution because it can break easily and is not generic at all. I would not even use polymorphism in that case.

I think it will be the easiest way. Just move the comparison method to the interface and override it in derived classes. Add the following lines to yor example:
class A
{
/*..................................................*/
virtual bool comp(const int) const { return false; }
virtual bool comp(const std::string) const { return false; }
virtual bool comp(const double) const { return false; }
};
template<class T>
class B : public A
{
/*..................................................*/
virtual bool comp(const T othr) const override { return othr == Var; }
};
void foo()
{
/*..................................................*/
if (i->comp(20))
{
/* do something*/
}
if (i->comp("Hello Stackoverflow"))
{
/* do something*/
}
/*..................................................*/
}

Related

c++ design: avoid iterating over types with an existing class hierarchy

Please consider the following (simplified) class hierarchy and processing functions:
struct msgBase
{
virtual int msgType() const=0;
};
struct msgType1:public msgBase
{
virtual int msgType() const{return 1;}
};
struct msgType2:public msgBase
{
virtual int msgType() const {return 2;}
};
void process(const msgType1& mt1)
{
// processing for message type 1
}
void process(const msgType2& mt2)
{
// processing for message type 2
}
void process(const msgBase& mbase)
{
switch(mbase.msgType())
{
case 1:
process(static_cast<const msgType1&>(mbase));
break;
case 2:
process(static_cast<const msgType2&>(mbase));
break;
}
}
In an integrated design, msgBase would be given a virtual "process" method, to avoid needing to iterate over the types.
If it's not possible or desirable to modify any of the classes, are there any alternatives to iterating over the types?
I've experimented with a decorator/factory pattern where a parallel hierarchy of classes encapsulates the given classes, and implements the necessary virtual functions, but this results in an awful lot of boilerplate, and the factory function still needs to iterate over the types!
I could replace the switch statement with a series of dyamic_casts, but that still leaves the same weaknesses.
As requested by Simon, here is what I mean by CRTP:
typedef <class Derived>
struct msgBase
{
virtual void process(){
// redirect the call to the derived class's process()
static_cast<Derived*>(this) -> process();
};
struct msgType1:public msgBase<msgType1>
{
void process(){
// process as per type-1
}
};
struct msgType2:public msgBase<msgType1>
{
void process(){
// process as per type-2
}
};
What's happening here? Consider this case:
msgBase* msg = new msgType1();
msg->process();
normally (without CRTP) this would only call msgBase::process(). But now, msgBase "knows" about msgType1 using the template, so it is redirected to msgType1::process at compile time.
Something like this could work:
These classes are used to do the casting automatically:
struct dispatcher_base {
virtual void process(const msgBase&) = 0;
};
template <class T>
struct dispatcher_impl : dispatcher_base {
void process(const msgBase& b) override {
::process(static_cast<const T&>(b));
}
};
We'll store them in a map:
auto g_table = std::map<int, std::unique_ptr<dispatcher_base>>{};
But now you have to initialize this table somewhere:
template <class T>
void register_msg() {
g_table[T{}.msgType()].reset(new dispatcher_impl<T>{});
}
...
register_msg<msgType1>();
register_msg<msgType2>();
You can add an assert to register_msg to make sure that msgTypes are unique.
Your process function will look like this:
void process(const msgBase& b) {
assert(g_table.find(b.msgType()) != g_table.end());
g_table[b.msgType()]->process(b);
}
You can replace assert with any other logic of course.
If you can't modify the classes then you can use decorators to get polymorphic type deduction.
struct DecorBase {
DecorBase(msgBase& b) : b_(b) {}
virtual ~DecorBase() {}
virtual void process() = 0;
msgBase& b_;
};
struct DecorType1 : public DecorBase {
DecorType1(msgType1& t1) : DecorBase(t1) {}
void process() override {
std::cout << "Processing Type 1" << std::endl;
}
};
struct DecorType2 : public DecorBase {
DecorType2(msgType2& t2) : DecorBase(t2) {}
void process() override {
std::cout << "Processing Type 2" << std::endl;
}
};
And use it like this:
msgType1 t1;
msgType2 t2;
DecorType1 dt1(t1); // Wrap objects in respective decorator.
DecorType2 dt2(t2);
DecorBase& base = dt2;
base.process(); // Uses polymorphism to call function in derived type.
This will require you to write a decorator for every derived type but at least you don't have to iterate over all types during the function call.

mixing templates with polymorphism

class A
{
friend void foo();
virtual void print_Var() const{};
};// does not contain variable Var;
template<class T>
class B : public A
{
T Var;
public:
B(T x):Var(x){}
void print_Var() const override
{
std::cout<<Var<<std::endl;
}
};
void foo()
{
std::array<std::unique_ptr<A>, 3> Arr = {
std::make_unique<B<int>>(100),
std::make_unique<B<int>>(20),
std::make_unique<B<std::string>>("Hello Stackoverflow")
};
std::shuffle(Arr.begin(), Arr.end(), std::mt19937(std::random_device()())); // 3rd parameter generated by Clang-Tidy
for (auto &i: Arr)
{
i->print_Var(); // OK
// auto z = i->Var // no member named Var in A
// obviously base class does not contain such variable
// if (i->Var==20) {/* do something*/}
// if (i->Var=="Hello Stackoverflow") {/* do something*/}
}
}
Explanation:
I want to iterate over array of pointers to A, which is filled with pointers to classes derived from A, and depending on what type is variable Var, do some if( ) statement.
Problem is that i cannot access Var, cause its not member of base class. However, it's possible to cout those values by, for example, overloaded function returning void. Could i write function in A class that returns templated type? like:
class A
{
<class T> GetVar()
}
Besides, I feel like I'm dealing with this problem in totally improper way. Can i mix templates and inheritance like that? If not, how should it be designed?
You have a few choices. I'll explain my preferred solution first.
1. Use dynamic dispatch
If you have an array of a base class type, why do you even want to do stuff with Var? That variable is specific to the child class. If you have a A somewhere, you shouldn't even care what B has or hasn't at that place.
Operations on the typed variable should be encapsulated in virtual function in the base class. If you want to do condition and stuff, maybe you could encapsulate that condition into a virtual function that returns a boolean.
2a. Drop the base class and use variant
Sometimes, you know in advance the amount of types that will go into that list. Using a variant and drop the base class is a good solution that may apply to your case.
Let's say you only have int, double and std::string:
using poly = std::variant<B<int>, B<double>, B<std::string>>;
std::array<poly, 3> arr;
arr[0] = B<int>{};
arr[1] = B<double>{};
arr[2] = B<std::string>{};
// arr[2] = B<widget>{}; // error, not in the variant type
std::visit(
[](auto& b) {
using T = std::decay_t<decltype(b)>;
if constexpr (std::is_same_v<B<int>, T>) {
b.Var = 2; // yay!
}
},
arr[0]
);
2b. Drop the base class and use generic functions
Drop the base class entirely, and template your functions that do operation on them. You can move all your function into an interface or many std::function. Operate on that instead of the function directly.
Here's an example of what I meant:
template<typename T>
void useA(T const& a) {
a.Var = 34; // Yay, direct access!
}
struct B {
std::function<void()> useA;
};
void createBWithInt {
A<int> a;
B b;
b.useA = [a]{
useA(a);
};
};
This is fine for cases where you only has a few operation. But it can quickly lead to code bloat if you have a lot of operation or if you have many types of std::function.
3. Use a visitor
You could create a visitor that dispatch to the right type.
This solution would be much close to what you except, but is quite combersome and can break easily when adding cases.
Something like this:
struct B_Details {
protected:
struct Visitor {
virtual accept(int) = 0;
virtual void accept(double) = 0;
virtual void accept(std::string) = 0;
virtual void accept(some_type) = 0;
};
template<typename T>
struct VisitorImpl : Visitor, T {
void accept(int value) override {
T::operator()(value);
}
void accept(double) override {
T::operator()(value);
}
void accept(std::string) override {
T::operator()(value);
}
void accept(some_type) override {
T::operator()(value);
}
};
};
template<typename T>
struct B : private B_Details {
template<typename F>
void visit(F f) {
dispatch_visitor(VisitorImpl<F>{f});
}
private:
virtual void dispatch_visitor(Visitor const&) = 0;
};
// later
B* b = ...;
b->visit([](auto const& Var) {
// Var is the right type here
});
Then of course, you have to implement the dispatch_visitor for each child class.
4. Use std::any
This is litteraly returning the variable with type erasure. You cannot do any operation on it without casting it back:
class A {
std::any GetVar()
};
I personnaly don't like this solution because it can break easily and is not generic at all. I would not even use polymorphism in that case.
I think it will be the easiest way. Just move the comparison method to the interface and override it in derived classes. Add the following lines to yor example:
class A
{
/*..................................................*/
virtual bool comp(const int) const { return false; }
virtual bool comp(const std::string) const { return false; }
virtual bool comp(const double) const { return false; }
};
template<class T>
class B : public A
{
/*..................................................*/
virtual bool comp(const T othr) const override { return othr == Var; }
};
void foo()
{
/*..................................................*/
if (i->comp(20))
{
/* do something*/
}
if (i->comp("Hello Stackoverflow"))
{
/* do something*/
}
/*..................................................*/
}

C++: store/remember type of template class

Let's assume we have a class like the following:
class AbstractContainer{
...
};
template <typename T>
class Container : public AbstractContainer {
T someFunction();
};
Now there is another class which has a member variable that shall store one of these containers. However, the template type shall not be fixed. Therefore, instead of declaring the member variable as of type Container, it's declared as of type AbstractContainer*, so a pointer at the base class. This pointer should be able to store all types of Container classes, regardless of the template parameter.
class Interface{
public:
Interface();
void doSth();
private:
AbstractContainer* container;
};
Let's assume the container is constructed in the constructor of the Interface class like this:
Interface::Interface(){
if (/* some condition */)
this->container = new Container<int>(25);
} else {
this->container = new Container<float>(25);
}
//here I'd need to remember of which type container is: int or float
}
So here I'd need to somehow store of which type my container is (int or float). I know it at this point of my program and it's totally deterministic. I need to store it, because later I might have to cast my AbstractContainer* back to a Container<int>* or a Container<float>*, for example in another function:
void Interface::doSth(){
//here I have to recall what the type was
if(/* type was int */) {
dynamic_cast<Container<int>&>(*(this->container)).someFunction();
} else {
dynamic_cast<Container<float>&>(*(this->container)).someFunction();
}
}
I have thought about using an enum that contains values for all different supported types and saving the type in an additional member variable of that enum type. Then I'd have to make a switch statement that checks for all the different possibilities and performs the correct cast. However, I wondered if there might not be an easier way.
What I'd basically like to do, is store the type used in the constructor of Interface and then recall it in Interface::doSth.
EDIT: I have to make clear that the function someFunction depends on the template parameter T. So it is not an option to make it virtual.
You may do
void Interface::doSth(){
if (auto* c_int = dynamic_cast<Container<int>*>(this->container)) {
c_int->someFunction();
} else if (auto* c_float = dynamic_cast<Container<float>*>(this->container)) {
c_float->someFunction();
}
}
But why not move someFunction() into the base class ? and use virtual method ?
Though Jarod42's answer is better, one way to do it is by using typeid:
void doSth()
{
if (typeid(*container).hash_code() == typeid(Container<int>).hash_code())
{
cout << "int" << endl;
}
else if (typeid(*container).hash_code() == typeid(Container<float>).hash_code())
{
cout << "float" << endl;
}
}
But you'll need at least a virtual function in the base class. You can make a virtual destructor, for example.
May be your answer is Curiously recurring template pattern.
template<class T, template<class> class U>
class AbstractContainer
{
void interface()
{
static_cast<U<T> *>(this)->implementation();
}
};
template<class T>
class Container : public AbstractContainer<T, Container>
{
void implementation()
{
}
};
Another alternative:
template <class T>
T doSth(Container<T> &container){
return container.someFunction(); //assume someFunction returns a T
}
You don't need a base class, no inheritance, no casts.
class AbstactObject {
public:
virtual ~AbstractObject() = 0;
virtual AbstractObject &doSomething() = 0;
}
template<class T>
class Object : AbstactObject {
public:
virtual ~Object();
virtual Object<T> &doSomething();
T &get();
private:
T t;
}
class AbstractContainer {
public:
virtual ~AbstractObject() = 0;
virtual AbstractObject &doSomething();
private:
AbstractObject *obj;
};
template<class T>
class Container : AbstactContainer {
public:
virtual ~Container();
virtual Object<T> &doSomething() {
return obj->doSomething();
};
}
class Interface {
public:
Interface();
void doSth();
private:
AbstractContainer* container;
};
Interface::Interface() {
if (/* some condition */)
container = new Container<int>(25);
} else {
container = new Container<float>(25);
}
}
void Interface::doSth() {
auto obj = container->doSomething();
auto val = obj.get();
}
when you want to get the T value
auto obj = container->doSomething();
auto val = obj.get();
Please check: Covariant return type
https://en.wikipedia.org/wiki/Covariant_return_type

Avoid switching on template parameters

Simplified I have the following class hierarchy:
class BaseVec {
public:
BaseVec() {};
virtual ~BaseVec() {};
virtual double get_double(int i) const = 0;
};
template<typename T>
class Vec : public BaseVec {
public:
Vec() { ... };
~Vec() { ... };
T get(int i) const { ... };
double get_double(int i) const {
return get(i);
};
};
In my project I repeatedly end up with code of the following form:
template<typename T>
double foo_template(void* p) {
Vec<T>* v = reinterpret_cast<Vec<T>*>(p);
// use v which involves calling get
return result;
}
double foo(void* p, int type) {
if (type == 0) {
return foo_template<double>(p);
} else if (type == 1) {
return foo_template<int>(p);
} else if (...) {
// etc.
} else {
//unsupported type
}
}
(I could use a switch and use enums, or first cast p to BaseVec and then do dynamic_casts, but the logic then remains the same)
This is not ideal to maintain. For example when I add an additional class I want to support I have to add a clause to each of the if-else-if blocks.
One possible way of simplifying this would be to cast p to BaseVec* and use the get_double method. However, since this method is called very often this results in poor performance. Furthermore, this is not alway possible: sometimes I want to call the get method as the type returned is important.
I experimented with the visitor-pattern, and although, this has some advantages, it still means I have to write a seperate piece of code for each possible template parameter.
Is there some way of making this code easier to maintain?
PS: I don't have (much) control over what comes into foo. foo gets called by an external programme (R to be exact). Therefore, I can only pass generic pointers, int, doubles and character vectors to foo.
PPS: Suggestions for a better title are also welcome.
First of all, don't use reinterpret_cast while converting to/from pointer to polymorphic class. You can write a simple pointer wrapper which allow you to use safe casting operator static_cast:
template <class Type>
class PointerWrapper
{
public:
PointerWrapper(Type* object);
PointerWrapper& operator=(Type* object);
Type* operator->();
protected:
Type* object;
};
template <class Type>
PointerWrapper<Type>::PointerWrapper(Type* object) :
object(object)
{
}
template <class Type>
PointerWrapper<Type>& PointerWrapper<Type>::operator=(Type* object)
{
this->object = object;
}
template <class Type>
Type* PointerWrapper<Type>::operator->()
{
return object;
}
Now you can write:
typedef PointerWrapper<BaseVec> BaseVecPointer;
template<typename T>
double foo(void* p) {
BaseVecPointer* vp = static_cast<BaseVecPointer*>(p);
// ...
// ... = (*vp)->get_double(...);
// ...
return result;
}
In this code polymorphism capabilities were used, i.e. function get_double was called instead of calling get.
But if you want to call just get, not get_double, i.e. you want to call template functions with different template arguments depending on the value of run-time variable, you can use the following method:
enum FooTypes
{
NoFooType = -1,
DoubleFooType = 0,
IntegerFooType = 1,
// ...
FooTypesCount
};
template<FooTypes fooType>
struct ChooseType
{
static
const FooTypes value = NoFooType;
typedef void Type;
};
template<>
struct ChooseType<DoubleFooType>
{
static
const FooTypes value = DoubleFooType;
typedef double Type;
};
template<>
struct ChooseType<IntegerFooType>
{
static
const FooTypes value = IntegerFooType;
typedef int Type;
};
Here you should write specializations of the class template ChooseType for all possible values of type variable.
Following code describes the function ChooseFoo which selects what specialization of foo_template function template should be called:
typedef double (*FooFunction)(void*);
template<FooTypes fooType>
FooFunction ChooseFooImpl(int type)
{
if (type == fooType)
{
if (ChooseType<fooType>::value != NoFooType)
{
return foo_template<typename ChooseType<fooType>::Type>;
}
else
{
return NULL;
}
}
else
{
return ChooseFooImpl<(FooTypes)(fooType - 1)>(type);
}
}
template<>
FooFunction ChooseFooImpl<NoFooType>(int type)
{
return NULL;
}
FooFunction ChooseFoo(int type)
{
return ChooseFooImpl<FooTypesCount>(type);
}
And this is foo function implementation:
double foo(void* p, int type)
{
FooFunction fooFunction = ChooseFoo(type);
if (fooFunction != NULL)
{
return fooFunction(p);
}
else
{
//unsupported type
// ...
}
}
Why not change foo_template to be:
template<typename T>
double foo_template(Vec<T>*) {
// use v which involves calling get
return result;
}
and foo to be:
template<typename T>
double foo (Vec<T>* v )
{
return foo_template(v)
}
and let argument deduction do the work?
(You can probably get rid of one of the functions, but I wanted to keep is as close to the original)
Automatic dispatch in C++ happens with runtime-polymorphism by means of virtua function and with static_type polymorphism by mnas of a static_Cast, but you need to know what type to cast.
With a different design, avoiding void*, you can do the following:
template<class Derived>
class static_polimorphic {};
template<class A>
A& upcast(static_polymorphic<A>& sa)
{ return static_cast<A&>(sa); }
template<class A>
const A& upcast(const static_polymorphic<A>& sa)
{ return static_cast<const A&>(sa); }
Now, you classes shold be like
class C1: public static_polymorphic<C1>
{
....
};
class C2: public static_polymorphic<C2>
{
....
};
Polymorphism will then apply as
template<class A>
void function(const static_polymorphic<A>& sa)
{
A& a = upcast(sa);
a.methods();
...
}
In other words, the type is anymore represented a base member variable, but by a base template parameter.
Note also that being the bases differentiated by the derived type, common functions will not reaqire to be virtual. You can so completely avoid runtimes-based polymorphism, unless you have to store different runtime-type created object into a same container or collection.
For that purpose you can use a second non-tempetised base with abstract virtual function as "launchers" for the one in the derived classes.
(May be better to use the runtime polymorphic one as first base, to simplify run-time pointer convertion, since there will be no offset)

c++ how to create a std::vector of functors

class A
{
public:
int x;
//create a vector of functors in B and C here
};
class B
{
public:
struct bFunctor
{
void operator()() const
{
//some code
}
};
};
class C
{
public:
struct cFunctor
{
void operator()() const
{
//some code
}
};
};
void main()
{
A obj;
//iterate through the vector in A and call the functors in B and C
}
My question is what should be the format of the vector in class A for calling functors in B and C? Or is the only way this is possible to have a base functor in A and make the functors in B and C derive from it? Or is there a better approach?
There are essentially two ways to approach this (that I can think of ATM):
Note: I would rename cFunctor and bFunctor to simply Functor in both cases. They are nested inside respective classes and thus such prefix makes little sense.
Type erased
Example of type erasure is std::function.
class A {
public:
int x;
std::vector<std::function<void(void)>> functors;
A() : functors { B::bFunctor(), C::cFunctor() }
{ }
};
If you need the functors to have more advanced behaviour, Boost.TypeErasure any might help.
Polymorphic
Create an abstract functor type.
Make B::bFunctor and C::cFunctor inherit from it.
Store vector of that abstract functor type smart pointers.
struct AbstractFunctor {
virtual void operator()() const = 0;
};
class B {
public:
struct Functor : public AbstractFunctor {
void operator()() const {
//some code
}
};
};
class A {
public:
int x;
std::vector<std::unique_ptr<AbstractFunctor>> functors;
A() {
// this could most probably be shortened with make_unique
functors.emplace_back(std::unique_ptr<AbstractFunctor>(new B::Functor()));
functors.emplace_back(std::unique_ptr<AbstractFunctor>(new C::Functor()));
}
};

Resources