A function overload depending on enum - c++

Sorry for the noob question, but I cannot seem to get my head around C++'s static nature. The problem: I have a class that returns an enum and depending on it I have to convert the said class using another class and return a vector. In code:
enum TYPES { TYPE_A, TYPE_B, TYPE C }
class A {
TYPES getType() {}
}
class B : public A {}
class C : public A {}
class D : public A {}
std::vector<?> convert_to_vector(const A& a) {
// depending on what enum is returned by a.getType()
// I have to convert a into B, C, or D class and return std::vector of
// an appropriate type, e.g. int for B, float for C, etc.
}
int main() {
A a;
auto v = convert_to_vector(a);
}
The simplest way would be using switch(a.getType()) but I have different return types in each case and using auto as the return type doesn't work. I have tried templates and template specification, but they don't accept the runtime variable that is return by a.getType(). I guess there must be some simple solution that I'm overlooking here, but I have run out of ideas at this point and would be grateful for any pointers.
Thanks!

You can't change the return type of a C++ function at runtime. But you can use a variant type:
std::variant<std::vector<int>, std::vector<float>> convert_to_vector(const A& a) {
if (a.getType() == TYPE_B)
return std::vector<int>();
if (a.getType() == TYPE_C)
return std::vector<float>();
throw std::logic_error("unsupported type");
}
If you don't have C++17, you can use boost::variant instead of std::variant.

I think instead of deciding the type of a vector on an enum a much better solution would be to have a parent class A which can have a vector inside it which is based on a template variable. In your classes B, C, D you can simply inherit A and specify a template type. So, when you create a new object for B, C, D you will already have a vector member for those objects. You can also have a virtual function convertToVec which you can override in the child classes depending on how you want to convert data into a vector.
template<class T>
class A {
std::vector<T> vec;
std::vector<T> GetVector() { return vec; }
virtual convertToVec() { .... }
}
class B : public A<bool> {}
class C : public A<float> {}
class D : public A<long long int> {}
int main() {
B b;
b.GetVector();
//A* b = new B();
//b->convertToVec();
}

While it's pretty hard to follow what exactly you are trying to achieve here, going to use switch-case is not a good idea, instead you'd better to leverage polymorphism. For example:
class A {
public:
virtual void convertToVector(AuxVectorConverter& aux) = 0;
};
class B {
public:
// Add here specific implementation
virtual void convertToVector(AuxVectorConverter& aux) {
aux.convertToVectorB(this);
}
};
class C {
public:
// Add here specific implementation
virtual void convertToVector(AuxVectorConverter& aux) {
aux.doSomethingC(this);
}
};
// Aux class
class AuxVectorConverter {
public:
convertToVector(A* a) {
a->convertToVector(this);
}
convertToVectorB(B* b) {
// Do code specific for B
}
convertToVectorC(C* c) {
// Do code specific for B
}
}
int main() {
AuxVectorConverter* aux;
A* a = ...; // Initialize here either with instance of B or C
// Now, based on run time aux class will issue appropriate method.
aux.convertToVector(a);
}
You might find more details here
UPDATE (Based on comment)
An alternative approach could be to define a map from TYPES to some abstract class which will align with the patter from above, e.g.:
// Map has to be initialized with proper implementation
// of action according to type
map<Types, AbstracatAction> actions;
// Latter in the code you can do:
aux.convertToVector(actions[a->getType()]);
And action will be defined pretty similar to hierarchy I've showed above, e.g.
class AbstractAction {
public:
virtual void convertToVector(AuxVectorConverter& aux) = 0;
};
class ActionB: public AbstractAction {
public:
virtual void convertToVector(AuxVectorConverter& aux) {
aux.covertToVectorB(this);
}
};

Related

Is it possible to cast from vector parent* to vector child* in a function without using templates

While working on a data import system I decided to store a lot of objects deriving from one class in a vector of pointers to the parent class. And then I would like to have a function that returns a vector of any type of child pointers (using paramaters that let me know what kind of child it is).
I managed to realize a similar and simplified code here, but it uses templates and casts and I feel like only casts could be enough. However the compiler does not want to do any cast from vector A* to vector B*.
EDIT: In the real code there are many child classes, not only B, so replacing the template by B is not an option, sorry for not being precise enough.
#include <vector>
using namespace std;
class A
{
public:
int attr;
A(): attr(1) {}
};
class B : public A
{
public:
B(): A() {attr = 2;}
};
template <typename O>
vector<O*> bees(vector<A*> vecA)
{
auto vecO = vector<O*>();
for (auto it = vecA.begin(); it != vecA.end(); it++)
{
if ((*it)->attr == 2)
{
vecO.push_back(reinterpret_cast<O*>(*it));
}
}
return vecO;
}
int main()
{
auto vecA = vector<A*>();
vecA.push_back(new A());
vecA.push_back(new B());
vecA.push_back(new B());
vector<B*> vecB = bees<B>(vecA);
}
So my question is : Is it possible to have a code do the same effect without using templates ? And if not does the compiler generate specific code with this one ? Knowing there would be theorically no difference in runtime no matter the template.
Thank you.
Since you want a function that can return vector of any type of child pointer so i believe template is needed to specify child type but certain things like reinterpret_cast etc. is not needed and here is sample implementation :
class A
{
public:
int attr;
A(): attr(1) {}
virtual ~A() {};
};
class B : public A
{
public:
B(): A() {attr = 2;}
};
template<typename T>
vector<T*> bees(const vector<A*> &vecA)
{
vector<T*> vec;
for (auto it = vecA.begin(); it != vecA.end(); it++)
{
T* ptr = dynamic_cast<T*>(*it);
if(ptr != nullptr)
{
vec.push_back(*it);
}
}
return vec;
}
We are using dynamic_cast because we are downcasting parent type to child type.Also for dynamic_cast to work we need virtual destructor/virtual function as it require RTTI
Inheritance and polymorphy are supposed to hide away different child types, so the rest of your code doesn't have to worry about specific types.
Casting objects to specific types is very likely not the right approach to whatever you're trying to do. Let the types decide how they are used and what they do, not the outside world.
If you want to filter a vector to get only objects with specific properties, you shouldn't look at their types, you should ask them if they have the properties you are looking for:
void FilterA(const std::vector<A>& source, std::vector<A>& destination, std::function<bool(const A&)> filter) {
std::copy_if(source.begin(), source.end(), std::back_inserter(destination), filter);
}
Then you can call it like this:
std::vector<A> filteredVecA;
FilterA(vecA, filteredVecA, [](const A& a){return a.HasSomePropertyYouCareAbout();});
You should consider moving the type checking inside the hierarchy (this uses templates, but no casts):
class A {
public:
virtual ~A(); // you _are_ in a hierarchy of objects
template<typename T>
virtual T* as() const { return nullptr; }
};
template<typename X>
class Convertible: public A {
template<typename T>
virtual T* as() const {
if constexpr(std::is_same_v<X, T>)
return this;
else
return nullptr;
}
};
class B: public Convertible<B> {
};
template <typename O>
vector<O*> bees(vector<A*> vecA)
{
auto vecO = vector<O*>();
foreach (auto ptr: vecA)
{
auto ptrO = ptr->as<O>();
if (ptrO)
vecO.push_back(ptrO);
}
return vecO;
}
Some points:
OP's comment:
I am using reinterpret cast because it I do not cast it just doesn't compile, and it feels to me like it is the most adequate here knowing I do not need to do any changes on the object.
dynamic_cast is usually a symptom of an insufficiently designed class hierarchy. Whenever you think "I can solve this with dynamic_cast" consider adding code to your class hierarchy instead.

C++ compile time type determination

I have two classes deriving from the same base class. on compile time it is known which one gets created based on a macro define. I have another class that is a user and calls member functions (different ones for each class). It looks like this:
class User() {
void useClass( Base* p ) {
#ifdef useA
p->aFun();
#else
p->bFun()
#endif
}
class Base() {}
class A : public Base {
void aFun();
}
class B : public Base {
void bFun();
}
class C {
C() {
#ifdef useA
p = new A();
#else
p = new B();
#endif
}
Base* p;
User m_user;
void doStuffWithUser() {
user.useClass( p );
}
}
I would like to reduce the amount of macros, so I am wondering if there is a better way to do this. In particular, the #ifdef in the User class doesn't look very nice to me. Is there a way to reproduce it without using the macro? Ideally without runtime checks to determine what type p is.
EDIT:
The two derived classes have different members that need to be called and despite the inheritance, this cant be changed.
A solution is the visitor pattern.
The idea is to have two classes : the visitor and the visited.
The visitor is used to call a function depending on the real type of the object. The visited is the object of your class hierarchy.
In your example, you could do:
class User() {
void useClass( Base* p ) {
p->visit(visitor);
}
class Base() {
virtual void visit(Visitor) = 0;
}
class A : public Base {
void aFun();
virtual void visit(Visitor v) override {
v.visit(this);
}
}
class B : public Base {
void bFun();
virtual void visit(Visitor v) override {
v.visit(this);
}
}
class Visitor {
void visit(B* b) {
b->bFun();
}
void visit(A* a) {
a->aFun();
}
}
By having this double dispatch with the visit function, you ensure that you call the function depending on the real type.
I don't think there is a compile time solution to your issue because in useClass (as it is now), there is no way (at compile time) to know the real type of p. If you want to have a compile time solution you need to do more changes. For example making useClass a template or overloading it, which mean you can't call useClass with a Base* any more ...
The fact that A and B share a common base class is irrelevant since they have different interfaces that you are using.
I would make C a template and store a pointer to the derived class instead of the base class:
template<typename T>
class CT {
public:
CT() {
p = std::make_unique<T>();
}
std::unique_ptr<T> p;
User m_user;
void doStuffWithUser() {
user.useClass(p);
}
};
Then you can simply overload useClass() to accept either A or B:
class User {
public:
void useClass(A* p) {
p->aFun();
}
void useClass(B* p) {
p->bFun();
}
};
Now you just have one compile time switch:
#ifdef useA
using C = CT<A>;
#else
using C = CT<B>;
#endif
You can rename aFun and bFun to Fun and make it virtual(also add it in Base class) and in useClass, use Fun method, compiler will figure out which method to use.
This will eliminate first macro.
For the second maybe you should use rewrite it in some other way, so you wouldnt use macros at all. I don't think you can reproduce this behavior without macros.
Maybe you should have some flag that you give to constructor, 1 to create object A or 0 to create object B and get this flag from user at the runtime.
EDIT
So maybe you can create function Fun that in class A calls aFun and in class B calls bFun.
You can create a template for User class and specialize it for class A and class B:
template<typename T>
class User
{
void useClass( Base* p );
}
template<>
class User<A>
{
void useClass( Base* p ) {p->aFun();}
};
template<>
class User<B>
{
void useClass( Base* p ) {p->bFun();}
};
Now in class C:
template<typename T>
class C {
C() {
p = new T();
}
Base* p;
User<T> m_user;
void doStuffWithUser() {
m_user.useClass( p );
}
}
As a final note, just avoid using new operator. Try std::unique_ptr or std::shared_prt
PS. I have not tested this code
if you do not want to change any interface you can use single #ifdef
class Base {};
class A : public Base {
public:
void aFun(){}
};
class B : public Base {
public:
void bFun(){}
};
#ifdef useA
typedef A impl_type;
auto correct_func = &impl_type::aFun;
#else
typedef B impl_type;
auto correct_func = &impl_type::bFun;
#endif
class User {
public:
void useClass( Base* p ) {
auto pointer = (static_cast<impl_type*>(p));
(pointer->*correct_func)();
}
};
class C {
C() {
p = new impl_type();
}
Base* p;
User m_user;
void doStuffWithUser() {
m_user.useClass( p );
}
};
Probably you could name both functions with the same name in A and B and make it virtual, so useClass will call only needed function.
Like
class User() {
void useClass( Base* p ) {
p->fun();
}
};
class Base() {
virtual void fun() = 0;
};
class A : public Base {
void fun();
};
class B : public Base {
void fun();
};
Also you can use some kind of constexpr function (if you are using c++11 standard or newer) to determine what type p is.
Edit:
After seeing comment, i think that you're probably can left yours aFun(), bFun(), and just add some fun() func which will be derived and call type-specific function.
Also, it may be helpful to try and create some adapter classes with same interfaces(as in gof patterns).
Edit2: I mean that there could be some function like
constexpr Base* chooseType(int a){
if(a == 0){
return new A();
} else {
return new B();
}
}
/////
C() {
int case = 0;
p = chooseType(case);
}
And it will be called in compile-time, so as choice of class.
If you can't change the interface, want to get rid of #ifdefs, and have compile-time guarantee of types being used, without run-time checks - I would suggest using combination of templates, and overloaded functions.
First of all, I would change class C to be a template:
template<typename Type>
class C
{
static_assert(std::is_base_of<Base, Type>::value, "Template argument of C is not base of Base!");
public:
C () {p = new Type;}
~C() {delete p;}
void fun () {u.useClass (p);}
private:
Type* p;
User u;
};
And, then would change User class to switch between different possible implementations of Base with overloaded functions:
class User
{
public:
void useClass (A* p) {p->aFun();}
void useClass (B* p) {p->bFun();}
};
And, then you would create object of C as follows:
C<A> ca;
If you forgot to implement type-specific useClass, or tried to use wrong type in C (i.e. not inherited from Base), you would get compile-time errors.
In addition, if some of the child classes of Base, that you want to switch between, have non-default constructors, you may pass a functor (e.g. std::function<Type*()>) to a C constructor, and use that to create an object.
Such a constructor may look like:
C (std::function<Type* ()> function) {p = function();}
And usage of it would look like:
C<Z> cz ([&]{return new Z(someInt);});

Workaround for dynamically adding members to C++ class

I would like to know how would you address such a problem:
I have a class Foo:
class Foo
{
public:
Foo() { }
~Foo() { }
float member1() { return _member1; }
private:
float _member1;
// other members etc...
}
A container class that, among other things, holds a container of pointers to Foo instances
class FooContainer
{
public:
FooContainer() { }
~FooContainer() { }
void addFoo(Foo* f) {_foos.push_back(f);}
private:
boost::ptr_vector<Foo> _foos;
}
My problem is this: at runtime I am required to "add" new (completely different) members to Foo, depending on the instructions from the GUI. I could address the problem by creating two "decorators" like this:
class Decorator1
{
public:
int alpha() { return _alpha; }
float beta() { return _beta; }
private:
int _alpha;
float _beta;
}
class Decorator2
{
typedef std::complex<float> cmplx;
public:
cmplx gamma() { return _gamma; }
double delta() { return _delta; }
private:
cmplx _gamma;
double _delta;
}
and then I would create two different Foo implementations:
class Foo1 : public Foo, public Decorator1
{ }
class Foo2 : public Foo, public Decorator2
{ }
and use each one according to the GUI command. However such a change would propagate through all my code and would force me to create two different versions for each class that uses Foo1 and Foo2 (e.g. I'd have to create FooContainer1 and FooContainer2).
A less intrusive way of doing this would be to create
class Bar: public Foo, public Decorator1, public Decorator2
{ }
and use this instead of Foo. In this case I'd call only the functions I need from Decorator1 and Decorator2 and ignore the others, but this seems to go against good OOP techniques.
Any suggestions regarding the problem ?
Why don't you use simple polymorphism like this?
class Foo
{
public:
Foo() { }
virtual ~Foo() { }
float member1() { return _member1; }
private:
float _member1;
// other members etc...
}
class Foo1 : public Foo
{
public:
int alpha() { return _alpha; }
float beta() { return _beta; }
private:
int _alpha;
float _beta;
}
class Foo2 : public Foo
{
typedef std::complex<float> cmplx;
public:
cmplx gamma() { return _gamma; }
double delta() { return _delta; }
private:
cmplx _gamma;
double _delta;
}
class FooContainer
{
public:
FooContainer() { }
~FooContainer() { }
void addFoo(Foo* f) {_foos.push_back(f);}
private:
boost::ptr_vector<Foo> _foos;
}
Then the client code need not change. According to the GUI command you can create Foo1 or Foo2 and add it to the single container. If necessary, you can use the dynamic_cast on Foo pointer to cast to Foo1 or Foo2. But, if you have written the client code properly, then this wouldn't be needed.
It sounds like you're looking to handle mixin-type functionality. To do that, you could use templates. This isn't run time in the sense that copies of each class will be generated, but it does save you the typing.
So for each decorator, do something like:
template<class TBase> class Decorator1 : public TBase
{
public:
void NewMethod();
}
Then you can, for example:
Foo* d = new Decorator1<Foo1>(...);
Of course, the only way to make this work at runtime is to decide which type you're going to create. However, you still end up with the type Foo, Foo1 and Decorator1 so you can cast between them/use RTTI as you need to.
For more on this, see this article and this document
Although I've suggested it as a potential solution, I personally would be tempted to go with the polymorphism suggestion if at all possible - I think that makes for better, easier to maintain code because parts of class implementations aren't scattered all over the place using mixins. Just my two cents - if you think it works, go for it.
the fundamental concept of a class is that it's encapsulated and hence that one cannot add members after the definition (though you can use polymorphism and create derived classes with additional members, but they cannot be called through pointer of the original class: you must cast them to derived which is dangerous), in particular not at run time.
So it seems to me you're requirement breaks the essential idea of OO programming. This suggests a simple solution: use non-member functions. They can be defined at any time, even run time (when you would also need to compile them). The overhead of the function pointer is the same as before (when you would need a pointer to a new member function).
How about policy based templates? Have a template class Foo that takes a class as a template parameter. Then, have two methods that call the decorator methods:
tempate <class Decor>
class Foo
{
public:
Foo() : { __d = Decor() }
~Foo() { }
float member1() { return _member1; }
Decor::method1type decoratorMember1() { return __d.getValueMethod1();}
Decor::method2type decoratorMember2() { return __d.getValueMethod2();}
private:
float _member1;
Decor __d;
// other members etc...
}
Then, in your complex decorator:
class Decor1 {
typedef std::complex<float> method1type;
typedef double method2type;
public:
method1type getValueMethod1() {return _gamma}
method2type getValueMethod2() {return _delta}
private:
method1type _gamma;
method2type _delta;
}
Same for the other. This way, your Foo code can have anything added to it, even if it's already compiled. Just make a declarator class. And instead of instantiating Foo1, do this:
Foo<Decor1> f;

C++ template specify type by Enum

I'm facing a problem :
I want to create a function which calls a specific template type constructor depending on a enum that the function will receive. By that i mean :
typedef ____ (Class<whatever>::*tabType)(int flag);
template<typename T>
static Class* Class<t>::createClassInstance(enum precision)
{
static const ___ createTab[] = {
Class<int>,
Class<double>
}
return (new createTab[precision](1));
}
There are a number of ways of achieving this sort of thing, but it sounds like you want to create an array (or map) of factory methods (one for each class), indexed by the enum variable. Each one calls the relevant constructor, and returns a new object of that type.
Of course, for this to make any sense, all of the classes must derive from a common base.
If the enum value is dynamic as a function argument, you'll have to use either a dispatch table or switch/if-else. Notice that your pseudo code does not clearly explain the requirement. Say, what exactly the createInstance function you wish to define and how is it going to be called?
I would say, just construct a std::map that maps the enum to a factory function (boost::function<>). Then you just add one entry for each type that you want, with its corresponding enum. To actually construct the factory functions. You can either have some static Create() function for each class and store a function pointer. Or, you can use Boost.Lambda constructor/destructor functors. Or, you can use Boost.Bind to construct functors that wrap a factory function that requires some number of parameters. Here is an example:
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/lambda/construct.hpp>
#include <map>
struct Base { };
struct Derived1 : public Base { };
struct Derived2 : public Base {
static Base* Create() { return new Derived2; };
};
struct Derived3 : public Base {
int value;
Derived3(int aValue) : value(aValue) { };
static Base* Create(int aValue) { return new Derived3(aValue); };
};
enum DerivedCreate { ClassDerived1, ClassDerived2, ClassDerived3 };
int main() {
std::map< DerivedCreate, boost::function< Base*() > constructor_map;
constructor_map[ClassDerived1] = boost::lambda::new_ptr<Derived1>();
constructor_map[ClassDerived2] = &Derived2::Create;
constructor_map[ClassDerived3] = boost::bind(&Derived3::Create, 42);
//now you can call any constructor as so:
Base* ptr = constructor_map[ClassDerived2]();
};
I might have made some slight syntax mistakes, but basically you should be able make the above work. Also, the fact that you have several class templates plays no role, once they are instantiated to a concrete class (like Class<int> or Class<double>) they are just like any other class, and the above idea should remain valid.
Extending your example, something like the following works:
enum Prec {INT, DOUBLE};
struct Base
{
virtual ~Base () = 0 {}
};
template<typename T> struct Class : public Base
{
static Base* create (int flag) {return new Class<T> (flag);}
Class (int flag) {}
};
typedef Base* (*Creator) (int flag);
Base* createClassInstance (Prec prec)
{
static const Creator createTab[] = {
Class<int>::create,
Class<double>::create
};
return createTab[prec] (1);
}
int main (int argc, char* argv[])
{
Base* c = createClassInstance (DOUBLE);
return 0;
}

How to implement function with vector of derived classes as parameter

(Related to a previous unanswered question I asked). I want to implement a function which can be called only with vectors of related classes as parameter.
For eq
if we have
class A;
class B: public A;
class C: public A;
class D
then it should be possible to call function with vector<A*>,vector<B*> or
vector <C*> but not vector <D*>
Any suggestions
I guess you already tried to create a method like
void doSomething(std::vector<A*>& things)
{
}
and tried do pass
std::vector<B*> bList = ...;
doSomething(bList);
right?
Why does the compiler complain? Because it would not make sense. Consider that doSomething() tries to do
things.push_back(new C());
This cannot work as "things" is actually a std::vector<B*>. However, if it were std::vector<A*>, push_back would work.
So what can we learn from this? What you're trying only makes sense if you only read from the vector, however, vector is not a read-only container.
A simple wrapper shows a possible solution (the wrapper can be adjusted to your needs, of course). However, I have to point out that the use of virtual methods might lead to performance penalties.
class A {};
class B : public A {};
template <class Base>
class AbstractVectorWrapper
{
public:
virtual size_t size() const = 0;
virtual Base* getElementAt(int index) const = 0;
};
template <class Base, class Derived>
class VectorWrapper : public AbstractVectorWrapper<Base>
{
private:
std::vector<Derived*> m_vector;
public:
explicit VectorWrapper(std::vector<Derived*> const& vector)
: m_vector(vector)
{
}
virtual size_t size() const
{
return m_vector.size();
}
virtual Base* getElementAt(int index) const
{
return m_vector[index];
}
};
void doSomething(AbstractVectorWrapper<A> const& wrapper)
{
for (size_t i=0;i<wrapper.size();i++)
{
A* a = wrapper.getElementAt(i);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<A*> as;
std::vector<B*> bs;
doSomething(VectorWrapper<A,B>(bs));
doSomething(VectorWrapper<A,A>(as));
return 0;
}
Is duck-typing good enough for you? Consider this code
template <class T>
void my_function (std::vector <T*> const &values) {
// Use features of A* here
}
This will fail to compile if you use features that pointers to T do not support. By using features of A I think it should be guaranteed that pointers to B and C will also work as expected. However, it would be possible to call this function with vectors of D *, provided D's interface complies with what my_function tries to do.