I am creating a MVC framework for my project in C++. Below is controller source/pseudo code snippet. As you can see, that I have to put explicit check for each type. I have stored type for each property of object(model). Is there a way to avoid this switch case?
for each property P of object:
switch(type of P)
{
case(type_int):
{
int value;
model->fetch(value, P->id);
writer->write(value, P->id);
break;
}
case(type_float):
{
float value;
model->fetch(value, P->id);
writer->write(value, P->id);
break;
}
}
#include<vector>
#include<algorithm>
#include<iostream>
template<typename T>
struct pred{
void operator()(T x)
{
//implemnt algorithm
}
T value;
};
class property{
};
int main()
{
std::vector<property> myShape;
std::for_each(myShape.begin(),myShape.end(), pred<property>());
std::cout<<"Done"<<std::endl;
}
Please use this template function in place of switch
template<typename T>
void func()
{
T value;
model->fetch(value, P->id);
writer->write(value, P->id);
}
Where does value actually come from, because you can use that to drive the generics. As given, there's no way to prevent the switch, because the switch also decides the type of the value. If replace the switch with a variant (assuming you didn't want runtime polymorphism) you can make this work.
The astute reader will note that of course, somewhere internally, a type switch still happens. The essential differences are that
variants can be compile-time optimized away[1], in which case the type switch need not be present in the generated code or is faster
the type switch is hidden, the programmer thinks on a higher abstraction level
That said, if it brings complexity, consider simpler options. This might be premature optimization
[1] in far more (complicated) cases than de-virtualization usually happens
Related
I have this architecture(in short version):
class BaseBatch {
virtual ~BaseBatch(){};
};
template<class T>
class Batch : public BaseBatch
{
void draw(T* data) {
do something..
}
};
class BatchManager
{
private:
static std::vector<BaseBatch*> batches;
public:
template <class T>
static void placeData(T* data){
//Loop through the entire container
bool found = false;
for (auto&& b: batches())
if (b->get_type() == typeid(T)) {
dynamic_cast<Batch<T>*>(b)->draw(data);
found = true;
}
//If no bach found, create a new One
if (not found) {
batches.push_back(new Batch<T>);
}
}
};
Problem is that the placeData function is called multiple (many) times per 1 loop and I think that the dynamic casting is a real pain for the performance but cannot figure out how can I solve this without using it. Is it really that problematic or I shouldn´t bother with it and keep using it? If i should avoid it, what would you suggest? Thanks
Instead of using std::vector<Batch*> use a std::unordered_map<std::type_index, std::unique_ptr<BaseBatch>>. To access a batch use batches.find(std::type_index(typeid(T))), then static_cast it to a Batch<T>*. static_cast has no runtime overhead. To create a new batch, use std::type_index(typeid(T)) as the key.
The performance of dynamic_cast likely isn't the issue here. In fact, with this solution calling typeid is likely just as bad as dynamic_cast. The real potential gain is the lookup speed of the unordered_map vs iterating through every element of a who-knows-how-big vector and trying a dynamic_cast.
void ChangeState(int newState)
{
nextState = newState;
//Change the state
switch( nextState ) ///the change still will have a case for everything
{
case STATE_INTRO:
{
vec.pop_back();
state ptr(new CIntroState);
vec.push_back(ptr);
break;
}
case STATE_MENU:
{
vec.pop_back();
state ptr(new CMainMState);
vec.push_back(ptr);
break;
}
}
}
I have this function that allows me to change my current state; however, I thought about it and this is going to be a huge switch statement by the time I am finished. Currently, it already has about 10 states in it, this is just some sample code. I am trying to do something a little different, but I am not sure how to go about it.
void ChangeState(something)
{
vec.pop_back();
state ptr(new something);
vec.push_back(ptr)
}
If I could bring it in this way, I could completely avoid the use of the switch statement and get the same end result. Does anyone know how to go about this? Any help would be greatly appreciated.
You need to link compile-time polymorphism (i.e., templates) and run-time polymorphism, as ryanbwork suggests. The challenge here is to try to avoid transforming your current form of repetitive code (the big switch) into a similarly verbose but more declarative form of repetitive code.
As another popular Stack Overflow question reveals, clone methods are usually the way one creates new instances of dynamically determined types at run-time. Cloning is really a specialization of the more general factory pattern, and you could create a set of factories for your types whose definition would be only a little more verbose than your current enumeration presumably is:
template <class T>
class factory {
public:
T* operator()() {return new T;}
};
factory<CIntroState> IntroState;
factory<CMainState> MainState;
// etc...
template <class Fac>
void ChangeState(Fac newStateFactory)
{
vec.pop_back();
vec.push_back(newStateFactory());
}
It looks like you need a combination of templates and polymorphism. With templates, you don't need to enumerate all the different types that you may pass into a function, as this will be done for you during compilation. To store all of these different types in the same vector, you'll need to have them all sub class some super-type which then allows you to store them side by side in a vector of super-type.
I want to write a function that calls several sub functions and return the result of these sub functions.
sub functions:
template<class A> A sub1(A a)
template<class B> B sub2(B b, int i)
template<class C> C sub3(C c, string p)
THE function will call these accordingly in the switch statement.
Sorry I only have pseudo code since I am confused with the issue and not start to write the code.
mf(string s)
{
int k;
k = process(s)
string
switch (k){
case 0:
return sub1(k);
case 1:
return sub2(s, k);
case 2:
return sub3(k, s);
default:
break;
}
}
How can I define mf above since there is no return type for it now? using template again?
By the way, my c++ compiler does support c++ 11 standard which I am not so familiar with.
C++ is basically a static-typed language, which means all types of expressions are decided at compile time rather than at run time.
Using dynamic-typing in a static-typed language is possible, but not recommended for widely use. Because doing so you're giving up almost all the polymorphism features provided by the language. You'll have to check types manually, or implement your own dynamic-type-based polymorphism.
If the data returned is not too complex, tagged structure is usually a good idea:
struct Value
{
enum {INT, FLOAT, PTR} type;
union
{
int int_data;
float float_data;
void *ptr_data;
};
};
For more complex data types with a lot of operations needed to support, you should consider using abstract interfaces and inheritance.
If you considered the problem seriously and believe that none of those methods above applies to your problem, and that dynamic typing is the best way, here are some options:
boost::any -- A unique container for all types. Need to test for types and convert them manually before use.
boost::variant -- A union-like container which supports unary polymorphic operations via boost::static_visitor.
Some programming frameworks have their own support for dynamic-typing. One example is QVariant in Qt. If you are in such a framework, it's usually recommended to use them instead of something else from another library.
If you need a function that returns the value of its sub function you need the same return type for all of them.
Here a small meaningless example:
double calculatedPositive(double value)
{
// Do stuff
}
double calculatedNegative(double value)
{
// Do stuff
}
double functionA(double value)
{
if(value > 0)
return calculatePositive(value);
else
return calculateNegative(value);
}
P.-S. We could provide you with a better answer if you'd say what you are trying to achieve ;)
What I would like to do (in C++) is create a 'Parameter' data type which has a value, min, and max. I would then like to create a container for these types.
E.g. I have the following code:
template <typename T>
class ParamT {
public:
ParamT() {
}
ParamT(T _value):value(_value) {
}
ParamT(T _value, T _vmin, T _vmax):value(_value), vmin(_vmin), vmax(_vmax) {
}
void setup(T vmin, T vmax) {
this->vmin = vmin;
this->vmax = vmax;
}
void setup(T value, T vmin, T vmax) {
setup(vmin, vmax);
setValue(value);
}
T operator=(const T & value) {
setValue(value);
}
void setValue(T v) {
value = v;
}
T getValue() {
return value;
}
operator T() {
return getValue();
}
protected:
T value;
T vmin;
T vmax;
};
typedef ParamT<int> Int;
typedef ParamT<float> Float;
typedef ParamT<bool> Bool;
In an ideal world my Api would be something like:
std::map<string, Param> params;
params["speed"] = PFloat(3.0f, 2.1f, 5.0f);
params["id"] = PInt(0, 1, 5);
or
params["speed"].setup(3.0f, 2.1f, 5.0f);
params["id"].setup(0, 1, 5);
and writing to them:
params["speed"] = 4.2f;
params["id"] = 1;
or
params["speed"].setValue(4.2f);
params["id].setValue(1);
and reading:
float speed = params["speed"];
int id = params["id"];
or
float speed = params["speed"].getValue();
int id = params["id"].getValue();
Of course in the code above, ParamT has no base class so I cannot create a map. But even if I create a base class for it which ParamT extends, I obviously cannot have different getValues() which return different types. I thought about many solutions, including setValueI(int i), setValuef(float f), int getValueI(), float getValueF(), or a map for ints, a map for floats etc. But all seem very unclean. Is it possible in C++ to implement the above API?
At the moment I am only concerned with simple types like int, float, bool etc. But I would like to extend this to vectors (my own) and potentially more.
It's a tough concept to implement in C++, as you're seeing. I'm always a proponent of using the Boost library, which has already solved it for you. You can typedef the complex boost variant template class to something more usable in your specific domain, so
typedef boost::variant< int, float, bool > ParamT;
class Param
{
public:
// initialize the variants
Param(ParamT min, ParamT max, ParamT value)
: m_Min(min), m_Max(max), m_Value(value) {}
// example accessor
template<typename OutT>
const ParamT& value()
{
return boost::get<OutT>(m_Value);
}
// other accessors for min, max ...
private:
ParamT m_Min, m_Value, m_Max;
};
Param speed(-10.0f, 10.0f, 0.0f);
float speedValue = speed.value<float>();
Now, to add another type to your variant (eg, long, std::string, whatever) you can just modify the typedef of ParamT; The catch, here, is that the burden of checking the types is on you - it'll throw an exception if you store a float and try to receive an int, but there's no compile-time safety.
If you want to get really crazy, you can implement an overloaded cast operator on a proxy object....
class ProxyValue
{
public:
ProxyValue(ParamT& value) : m_Value(value) {}
template<typename ValueT>
operator ValueT()
{
return boost::get<ValueT>(m_Value);
}
private:
ParamT& m_Value;
};
You'd return this from a non-templated value() function in Param, instead of the variant itself. Now you can assign a value without the template call..
Param speed(-10.0f, 0, 10);
float speedValue = speed.value();
Though fair warning, you're stepping into meta-programming hell here. Here thar be dragons. And as always, this is not a complete solution, just a pointer. YMMV.
Heres a roughly working version showing how to use it, and the failures that are easy to hit.
Ok, I'm bored at work (just waiting for something to compile), so here's another solution. Just have one type Param that stores three Values. Those values can by dynamically typed and can store ints and floats (and anything else you want them to).
class Value
{
private:
union
{
int i,
float f
} val;
DataTypeCode dtc;
public
Value() : val.i(0), dtc(INT) {}
Value(int i) : val.i(i), dtc(INT) {}
Value(float f) : val.f(f), dtc(FLOAT) {}
Value& operator=(int i)
{
val.i=i;
dtc=INT;
return *this;
}
Value& operator=(float f)
{
val.f=f;
dtc=FLOAT;
return *this;
}
operator int()
{
switch (dtc)
{
case INT: return val.i;
case FLOAT: return (int)val.f;
}
return 0;
}
operator float()
{
switch (dtc)
{
case INT: return (float)val.i;
case FLOAT: return val.f;
}
return 0;
}
}
class Param
{
private:
Value value, min, max
public:
Param(Value value, Value min, Value max) : value(value), min(min), max(max) {}
}
note, this still requires that DataTypeCode enum that I have in my other answer.
Now to access it, all you have to do is this:
std::map<string:Param> Params;
Params["speed"]=Param(1.4,0.1,5.6)
float speed=Params["speed"]
the cast operators along with the overloaded constructors and operator= functions will automatically convert among the types for you.
You can use either boost::any (to be able to store any type) or boost::variant (to store any type from a fixed set of prespecified types); however, the boost::program_options library largely already does what you want. I would strongly advise that you use boost::program_options rather than rolling this library yourself. I should point out that there is a major downside to what you are doing; you are validating types manually at runtime, which makes it easy for various errors to slip through. I strongly recommend using protocol buffers as a configuration language, as you get stronger type-checking that way.
A question I have about your design is why do you need to support all these value types? Performance, type safety, numeric accuracy, or simplicity/ease of use? It's going to be tough to get your interface to support all of these.
One simple way to solve the question, as you posed it, would be to pick a single numeric type that supports all the values you are interested in. In general, a double should suffice. It will be obvious to users what is going on under the hood, and you don't need to do anything weird with your implementation.
If you need perfect storage, you could implement your own numeric type that can do conversions (implicit or explicit) to various numeric types, and maintain perfect storage if you convert to/from the same type. If you're really concerned about perfect storage, you could also make it throw if you try to do a conversion back to the wrong type. This is like a strongly typed union. I believe the boost library has a type like this. Edit: Nicholas M T Elliott's answer already mentions this - boost variant.
If you like the even-more-explicit interface that you have here, with your GetValueAsInt/SetValueAsInt interface, you can still make it slightly simpler. Combine the setters, since C++ supports function overloading for parameters: void SetValue(int value) void SetValue(float value). C++ does not support function overloading for return types, though, so you cannot combine the getters.
Edit:
No matter which of these you pick, you're going to have a problem making it generic, or adding new types to it later. You must modify the property map's value type every time you want to support an new class.
The simplest way around this in C++ is to use a void* as your value type, and do casts to convert it to and from your target type. Your library could provide a template wrapper to do this cast, and throw if the cast fails.
This is similar to using "object" in Java/C#
Edit:
As Michael Aaron Safyan suggested, you could use boost::any.
In the end, you need to think about this: must your design include property dictionaries? If it doesn't have to have it, then you could benefit from the compiler's static analysis if you abandon this idea. Any behavior you push off to runtime will cause bugs that you won't find at compile time. It does make it faster to get the code running, but it makes your runtime error handling harder, and can hurt perf.
Well, it's easy to make a container store just about anything. As you said, you could make a common base class and have the map just store a pointer to that. The hard part is knowing what data type they are when you're retrieving them and using it. I have something like this in my main project where I'm mixing compile-time type determined c++ code and run-time type determined code from another language. So I embed into the class it's datatype code so that I can do a switch() statement on it. You could have something like this:
enum DataTypeCode
{
UNKNOWN,
INT,
FLOAT
};
template <class DataType>
DataTypeCode GetDataTypeCode()
{
return UNKNOWN;
}
template <>
DataTypeCode GetDataTypeCode<int>()
{
return INT;
}
template <>
DataTypeCode GetDataTypeCodE<float>(
{
return FLOAT;
}
class BaseParam
{
public:
virtual ~BaseParam() {}
virtual DataTypeCode GetDataTypeCode()=0;
};
template <class DataType>
class Param : public BaseParam
{
public:
DataTypeCode GetDataTypeCode()
{
return ::GetDataTypeCode<DataType>();
}
}
and you have to store it as a pointer to take care of polymorphism:
std::map<string,BaseParam*> Params
Params["speed"]=new Param<float>(...)
BaseParam* pMyParam=Params["speed"];
switch (pMyParam->GetDataTypeCode())
{
case INT:
//dosomething with int types
case FLOAT:
//dosomething with float types
}
It's not pretty, but it'll get the job done. Normally, I'll end up wrapping the std::map<string, BaseParam*> inside of another class to hide the fact that it's storing a pointers. I like to make my APIs hide the use of pointers as much as possible, it makes it easier for the junior programmers on my team to deal with it.
I have a set of classes that describe a set of logical boxes that can hold things and do things to them. I have
struct IBox // all boxes do these
{
....
}
struct IBoxCanDoX // the power to do X
{
void x();
}
struct IBoxCanDoY // the power to do Y
{
void y();
}
I wonder what is the 'best' or maybe its just 'favorite' idiom for a client of these classes to deal with these optional capabilities
a)
if(typeid(box) == typeid(IBoxCanDoX))
{
IBoxCanDoX *ix = static_cast<IBoxCanDoX*>(box);
ix->x();
}
b)
IBoxCanDoX *ix = dynamic_cast<IBoxCanDoX*>(box);
if(ix)
{
ix->x();
}
c)
if(box->canDoX())
{
IBoxCanDoX *ix = static_cast<IBoxCanDoX*>(box);
ix->x();
}
d) different class struct now
struct IBox
{
void x();
void y();
}
...
box->x(); /// ignored by implementations that dont do x
e) same except
box->x() // 'not implemented' exception thrown
f) explicit test function
if(box->canDoX())
{
box->x();
}
I am sure there are others too.
EDIT:
Just to make the use case clearer
I am exposing this stuff to end users via interactive ui. They can type 'make box do X'. I need to know if box can do x. Or I need to disable the 'make current box do X' command
EDIT2: Thx to all answerers
as Noah Roberts pointed out (a) doesnt work (explains some of my issues !).
I ended up doing (b) and a slight variant
template<class T>
T* GetCurrentBox()
{
if (!current_box)
throw "current box not set";
T* ret = dynamic_cast<T*>(current_box);
if(!ret)
throw "current box doesnt support requested operation";
return ret;
}
...
IBoxCanDoX *ix = GetCurrentBox<IBoxCanDoX>();
ix->x();
and let the UI plumbing deal nicely with the exceptions (I am not really throwing naked strings).
I also intend to explore Visitor
I suggest the Visitor pattern for double-dispatch problems like this in C++:
class IVisitor
{
public:
virtual void Visit(IBoxCanDoX *pBox) = 0;
virtual void Visit(IBoxCanDoY *pBox) = 0;
virtual void Visit(IBox* pBox) = 0;
};
class IBox // all boxes do these
{
public:
virtual void Accept(IVisitor *pVisitor)
{
pVisitor->Visit(this);
}
};
class BoxCanDoY : public IBox
{
public:
virtual void Accept(IVisitor *pVisitor)
{
pVisitor->Visit(this);
}
};
class TestVisitor : public IVisitor
{
public:
// override visit methods to do tests for each type.
};
void Main()
{
BoxCanDoY y;
TestVisitor v;
y.Accept(&v);
}
Of the options you've given, I'd say that b or d are "best". However, the need to do a lot of this sort of thing is often indicative of a poor design, or of a design that would be better implemented in a dynamically typed language rather than in C++.
If you are using the 'I' prefix to mean "interface" as it would mean in Java, which would be done with abstract bases in C++, then your first option will fail to work....so that one's out. I have used it for some things though.
Don't do 'd', it will pollute your hierarchy. Keep your interfaces clean, you'll be glad you did. Thus a Vehicle class doesn't have a pedal() function because only some vehicles can pedal. If a client needs the pedal() function then it really does need to know about those classes that can.
Stay way clear of 'e' for the same reason as 'd' PLUS that it violates the Liskov Substitution Principle. If a client needs to check that a class responds to pedal() before calling it so that it doesn't explode then the best way to do that is to attempt casting to an object that has that function. 'f' is just the same thing with the check.
'c' is superfluous. If you have your hierarchy set up the way it should be then casting to ICanDoX is sufficient to check if x can do X().
Thus 'b' becomes your answer from the options given. However, as Gladfelter demonstrates, there are options you haven't considered in your post.
Edit note: I did not notice that 'c' used a static_cast rather than dynamic. As I mention in an answer about that, the dynamic_cast version is cleaner and should be preferred unless specific situations dictate otherwise. It's similar to the following options in that it pollutes the base interface.
Edit 2: I should note that in regard to 'a', I have used it but I don't use types statically like you have in your post. Any time I've used typeid to split flow based on type it has always been based on something that is registered during runtime. For example, opening the correct dialog to edit some object of unknown type: the dialog governors are registered with a factory based on the type they edit. This keeps me from having to change any of the flow control code when I add/remove/change objects. I generally wouldn't use this option under different circumstances.
A and B require run time type identification(RTTI) and might be slower if you are doing a lot checks. Personally I don't like the solutions of "canDoX" methods, if situations like this arise the design probably needs an upgrade because you are exposing information that is not relevant to the class.
If you only need to execute X or Y, depending on the class, I would go for a virtual method in IBox which get overridden in subclasses.
class IBox{
virtual void doThing();
}
class IBoxCanDoX: public IBox{
void doThing() { doX(); }
void doX();
}
class IBoxCanDoY: public IBox{
void doThing() { doY(); }
void doY();
}
box->doThing();
If that solution is not applicable or you need more complex logic, then look at the Visitor design pattern. But keep in mind that the visitor pattern is not very flexible when you add new classes regularly or methods change/are added/are removed (but that also goes true for your proposed alternatives).
If you are trying to call either of these classes actions from contingent parts of code, you I would suggest you wrap that code in a template function and name each class's methods the same way to implement duck typing, thus your client code would look like this.
template<class box>
void box_do_xory(box BOX){
BOX.xory();
}
There is no general answer to your question. Everything depends. I can say only that:
- don't use a), use b) instead
- b) is nice, requires least code, no need for dummy methods, but dynamic_cast is a little slow
- c) is similar to b) but it is faster (no dynamic_cast) and requires more memory
- e) has no sense, you still need to discover if you can call the method so the exception is not thrown
- d) is better then f) (less code to write)
- d) e) and f) produce more garbage code then others, but are faster and less memory consuming
I assume that you will not only be working with one object of one type here.
I would lay out the data that you are working with and try to see how you can lay it out in memory in order to do data-driven programming. A good layout in memory should reflect the way that you store the data in your classes and how the classes are layed out in memory. Once you have that basic design structured (shouldn't take more than a napkin), I would begin organizing the objects into lists dependent on the operations that you plan to do on the data. If you plan to do X() on a collection of objects { Y } in the subset X, I would probably make sure to have a static array of Y that I create from the beginning. If you wish to access the entire of X occasionally, that can be arranged by collecting the lists into a dynamic list of pointers (using std::vector or your favorite choice).
I hope that makes sense, but once implemented it gives simple straight solutions that are easy to understand and easy to work with.
There is a generic way to test if a class supports a certain concept and then to execute the most appropriate code. It uses SFINAE hack. This example is inspired by Abrahams and Gurtovoy's "C++ Template Metaprogramming" book. The function doIt will use x method if it is present, otherwise it will use y method. You can extend CanDo structure to test for other methods as well. You can test as many methods as you wish, as long as the overloads of doIt can be resolved uniquely.
#include <iostream>
#include <boost/config.hpp>
#include <boost/utility/enable_if.hpp>
typedef char yes; // sizeof(yes) == 1
typedef char (&no)[2]; // sizeof(no) == 2
template<typename T>
struct CanDo {
template<typename U, void (U::*)()>
struct ptr_to_mem {};
template<typename U>
static yes testX(ptr_to_mem<U, &U::x>*);
template<typename U>
static no testX(...);
BOOST_STATIC_CONSTANT(bool, value = sizeof(testX<T>(0)) == sizeof(yes));
};
struct DoX {
void x() { std::cout << "doing x...\n"; }
};
struct DoAnotherX {
void x() { std::cout << "doing another x...\n"; }
};
struct DoY {
void y() { std::cout << "doing y...\n"; }
};
struct DoAnotherY {
void y() { std::cout << "doing another y...\n"; }
};
template <typename Action>
typename boost::enable_if<CanDo<Action> >::type
doIt(Action* a) {
a->x();
}
template <typename Action>
typename boost::disable_if<CanDo<Action> >::type
doIt(Action* a) {
a->y();
}
int main() {
DoX doX;
DoAnotherX doAnotherX;
DoY doY;
DoAnotherY doAnotherY;
doIt(&doX);
doIt(&doAnotherX);
doIt(&doY);
doIt(&doAnotherY);
}