Reducing amount of if/if code (C++) - c++

In my program I have to create an object, which looks like that:
Library::Param1<Library::Param2>::Param3 (don't know how to name Param, types maybe?)
Similar to std::vector<std::string>::iterator.
So, these Param's need to be changed by strings. For example:
if(param1 == "1_VALUE1")
{
if(param2 == "2_VALUE1")
{
MyLib::1_VALUE1<MyLib::2_VALUE1>::Param3 obj;
//Obj is used
}
//15+ similar if-statements, where only 2_VALUE1 changes
}
/*15+ similar if-statements, where only 1_VALUE1 changes,
but the contents remain same (again 15+ if-statements)*/
using namespace MyLib; is not neseccary.
So, I need to reduce amount of those if-statements, but I do not know the way to do it. I think it could be done with templates, but I am not familiar with them, so, I guess, I would need a code sample.
Sorry for the bad english, if any more info is needed - let me know. Thank you.
--- EDIT: Library (CryptoPP) type-definitions:
Since errors are only on Param1, posting one variation of it:
//! CBC mode with ciphertext stealing
template <class CIPHER>
struct CBC_CTS_Mode : public CipherModeDocumentation
{
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_CTS_Encryption> Encryption;
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_CTS_Decryption> Decryption;
};

I agree with Mark B that a factory would be nice, but I'm not sure if this is possible if you do not have a base class that all these types inherit from. If I understand the problem correcty, you have 15 types for Value 1 and 15 types for Value2 which leads to 15*15 if-statements. You can reduce them to 2*15 with the following approach: (untested)
---EDIT1: changed order of methods ---
template
void level2()
{
typename T1_T2::Param3 obj;
doSomething(obj);
}
template <template<class> class T1>
void level1(std::string param2)
{
if (param2 == "2_VALUE1")
level2<T1<MyLib::2_Value1> >();
if (param2 == "2_VALUE1")
level2<T1<MyLib::2_Value2> >();
...
}
void level0(std::string param1, std::string param2)
{
if (param1 == "1_VALUE1")
level1<MyLib::1_Value1>(param2);
if (param2 == "1_VALUE2")
level1<MyLib::1_Value2>(param2);
...
}
--- EDIT2 ---
To help you figure out why you can't compile, you can start with this sample code (compiles on Visual Studio 2008):
void doSomething(int x)
{
}
struct Type2_1 {};
template <class T2>
struct Type1_1
{
typedef int Param3;
};
template <class T2>
struct Type1_2
{
typedef int Param3;
};
template <template<class> class T1>
void level1(std::string param2)
{
if (param2 == "2_VALUE1")
level2<T1<Type2_1> >();
}
void level0(std::string param1, std::string param2)
{
if (param1 == "1_VALUE1")
level1<Type1_1>(param2);
if (param2 == "1_VALUE2")
level1<Type1_2>(param2);
}
template <class T1_T2>
void level2()
{
typename T1_T2::Param3 obj;
doSomething(obj);
}
int main(int argc, char* argv[])
{
level0("1_VALUE1", "2_VALUE1");
return 0;
}
Please note that "doSomething()" should be whatever you want MyLib to do with your obj; Returning obj from level0/1/2 won't work without a base class.

Instead of changing the type dynamically using if statements like that, which isn't well supported by C++, consider using something like a factory pattern instead.
Basically you set up a hierarchy of classes that have virtual methods that implement what you're trying to do in the if cases. You then make a function that creates the appropriate child class from a set of strings, and then you call go or whatever on the created instance.

Related

Using C++ template with std::function and std::bind

I am trying to create a template class which would in turn generate a wrapper over a function. The class will then return the wrapper as result. I would like to use template to have general class that will work with any function with different signatures, such as:
std::function<void()>task = std::bind(fun1, param1, param2);
std::function<int(int, int)>task = std::bind(fun2, param1, param2);
I would like to have something like this:
template <typename T1, typename T2>
class A {
A (string param1, string param2) {
// The created wrapper here i.e. 'task' will be returned by the class.
function<T1>task = bind(T2, param1, param2);
}
// Return the created wrapper in the constructor.
function<T1> returnWrapper() {
return task;
}
};
The code above is mostly a pseudo code since it cannot be compiled, but gives an idea about what I am looking for. Is there any solution for this? I think there should be more than simply use a template for a function's signature. Any help would be highly appreciated. I also would like to be able to pass arbitrary number of parameters to 'bind' if possible.
I think I solved the problem! I had to define a class which takes two type names inside a template and pass one of them to std::function as function signature after currying and use the second one in the constructor to define the curried function (result function after wrapping) in std::bind. Then everything worked fine! There might be some better solution, but this was the best and more or less clear solution I got. Here is the got snippet of the solution I found! Hope it helps the other with the same issue:
#include <iostream>
#include <functional>
using namespace std;
class A {
private:
template <typename T1, typename T2>
class B {
private:
function<T1>ff;
public:
B(T2 fun) {
ff = bind(fun, 1, placeholders::_1);
}
virtual ~B() {
}
int exec(int x) {
return ff(x);
}
};
static int myFun(int x, int y) {
return x + y;
}
public:
A() {
};
int test() {
B<int(int), int (*)(int, int)> b(&myFun);
return b.exec(10);
}
virtual ~A() {
};
};
int main() {
A a;
// Correct result is '11' since we pass 11 and 1 is in the curried function.
cout << "test result: " << a.test() << endl;
return 0;
}

If-else based on which typedef is being used

I've seen similar questions to this on SO but haven't found an answer for what I'm looking to do. I have two typedefs, only one of which will be used (other will be commented out):
typedef Student StudentType;
typedef StudentPF StudentType;
I want to use the alias StudentType for whichever one I'm currently using. Later on I have two different sets of code and I want to pick which set to run depending on whether StudentType is a Student or a StudentPF (Student taking course as Pass/Fail).
Is there a way to have something to this effect?
if (StudentType is of type StudentPF)
//do these things
else
//do these different things
The reason I'm attempting to do this is so I can change the behavior of my program just by simply commenting out one line and commenting in another if I keep the headers for both Student and StudentPF included.
Write a function template. Specialize it for each of the types you are interested in. Instantiate it with your typedef type.
template<typename T>
void DoStuff();
template<>
void DoStuff<Student>()
{
...
}
template<>
void DoStuff<StudentPF>()
{
...
}
int main()
{
DoStuff<StudentType>();
}
Obviously, Student and StudentPF aren't entirely interchangeable. So they ought to have something in their public interfaces letting you tell them apart. Maybe something like:
class Student {
public:
constexpr static bool is_pf = false;
// ...
};
class StudentPF {
public:
constexpr static bool is_pf = true;
// ...
};
void my_func() {
if (StudentType::is_pf)
;
}
But if you can't change Student or StudentPF, there's always:
#include <type_traits>
void my_func() {
if (std::is_same<StudentType, StudentPF>::value)
;
}
Neither of those will work if the code in the if or else clause won't compile for the "wrong" type. In that case, you would need some sort of static dispatch function.
You can use standard type traits for this :
if (std::is_same<StudentType, StudentPF>::value)
//do these things
else
//do these different things

Macro alternative for C++ code generation

My settings module has some redundant code:
#include <QSettings>
class MySettings
{
public:
// param1
void setParam1(QString param1) { _settings.setValue("param1", param1); }
string param1() { return _settings.value("param1").toString(); }
// param2
void setParam2(int param2) { _settings.setValue("param2", param2); }
int param2() { _settings.value("param2").toInt(); }
// param3
void setParam3(int param3) { _settings.setValue("param3", param3); }
int param3() { _settings.value("param3").toInt(); }
private:
QSettings _settings;
}
I managed to reduce the amount of code to write by using a macro. Here is an example for the QString parameter type:
#define INTSETTING(setter, getter) \
void set##setter(QString getter) { settings.setValue(#getter, getter);} \
QString getter() {return settings.value(#getter).toString();}
Since I'm using C++, I know that macro usage is bad. I'm looking for a cleaner alternative.
I gave a Qt example (QString) but it is a more general question.
Edit:
The macros make the definition of the above class much simpler:
class MySettings
{
public:
STRINGSETTING(Param1, param1)
INTSETTING(Param2, param2)
INTSETTING(Param3, param3)
STRINGSETTING(DefaultTitle, defaultTitle)
INTSETTING(MaxDocCount, maxDocCount)
private:
QSettings _settings;
}
You can either answer this in a religious fashion, or you can go back to the old principle: if it makes your code more readable, do it.
There are a lot of people who answer this in a religious way, they just hate the preprocessor and everything that's to do with it, and ban its use from their code.
On the other hand, there are people who routinely define macros to do repetitive task, I have done so on several occasions, most frequently just defining a macro for the use within a single function (used much in the way you can define subfunctions in GNU-C).
I think, the way people think about it is quite similar to the way people think about the goto statement: Most deamonize its use, others say it has its positive uses and should not be viewed as evil in itself. You need to decide this for yourself.
Here is one way that does not use macros:
class MySettings
{
public:
template <size_t N>
void setParam(QString param) { _settings.setValue(names[N], param); }
template <size_t N, typename T>
T param() { return _settings.value(names[N]).toString(); }
private:
QSettings _settings;
const char* names[3] = { "param1", "param2", "param3" };
}
You change the syntax a little so say e.g. settings.setParam<1>("string") and settings.param<1, string>() but in any case names param1, param2 etc were not so informative.
The only inconvenience is that the caller needs to specify the return type of param() apart from the parameter number. To get rid of this, you can specify all parameter types within MySettings, like this:
class MySettings
{
using types = std::tuple<string, int, int>;
public:
template<size_t N>
void setParam(QString param) { _settings.setValue(names[N], param); }
template<size_t N>
typename std::tuple_element<N, types>::type
param() { return _settings.value(names[N]).toString(); }
private:
QSettings _settings;
const char* names[3] = { "param1", "param2", "param3" };
}
You could of course further generalize this class to be used as a base for other settings classes. Within the base, the only things that need to be customized are members types and names.
However, keep in mind that if parameter names are informative indeed unlike your example, e.g. setTitle, setColor etc. then most probably there is no way to avoid macros. In this case, I prefer a macro that generates an entire struct rather than a piece of code within another class, hence probably polluting its scope. So there could be a struct for each individual parameter, generated by a macro given the parameter name. The settings class would then inherit all those individual structs.
EDIT
I "forgot" generalizing toString() in param() (thanks #Joker_vD). One way is this:
template<size_t N>
typename std::tuple_element<N, types>::type
param() {
using T = typename std::tuple_element<N, types>::type;
return get_value(type<T>(), _settings.value(names[N]));
}
where get_value<T>() is a helper function that you need to define and overload for the types supported by QSettings, calling the appropriate conversion member function for each type, for instance
template<typename V>
string get_value(type<string>, const V& val) { return val.toString(); }
template<typename V>
int get_value(type<int>, const V& val) { return val.toInt(); }
and type is just a helper struct:
template<typename T>
struct type { };
If QSettings itself was designed with templates in mind, you wouldn't need this. But you probably wouldn't need a wrapper in the first place.
Hiding members is good. But when you let the user edit/see them, you should impose some constraints: in each setter there should be a check before assigning the element a new value (which might even make your application crash).
Otherwise, there is little difference if the data was public.

static if in plain c++?

Problem in short:
How could one implement static if functionality, proposed in c++11, in plain c++ ?
History and original problem:
Recently I came up with a problem like this. I need a class Sender with an interface like
class Sender
{
void sendMessage( ... );
void sendRequest( ... );
void sendFile( ... );
// lots of different send methods, not important actually
}
In some cases I will need to create a DoubleSender, i.e. an instance of this class, which would call its methods twice, i.e. when calling, let's say, a sendMessage(...) method, the same message has to be sent twice.
My solutions:
First approach:
Have an isDouble member, and in the end of each method call make a check
sendMessage(...) { ... if( isDouble ) { sendMessage( ... ); }
Well, I don't want this, because actually I will need double posting very recently, and this part of code in time-critical section will be 98% passive.
Second approach:
Inherit a class DoubleSender from Sender, and implement its methods like:
void DoubleSender::sendMessage( ... )
{
Sender::sendMessage(...);
Sender::sendMessage(...);
}
Well, this is acceptable, but takes much space of unpleasant code (really much, because there are lots of different send.. methods.
Third approach:
Imagine that I am using c++11 :). Then I can make this class generic and produce the necessary part of code according to tempalte argument using static if:
enum SenderType { Single, Double };
template<SenderType T>
class Sender
{
void sendMessage(...)
{
// do stuff
static if ( T == Single )
{
sendMessage(...);
}
}
};
This is shorter, easier to read than previous solutions, does not generate additional code and... it's c++11, which I unfortunately cannot use in my work.
So, here is where I came to my question - how can I implement static if analog in c++ ? Also, I would appreciate any other suggestions about how to solve my original problem.
Thanks in advance.
Quoting #JohannesSchaubLitb
with my static_if that works on gcc one can do it :)
in some limited fashion
(see also here)
This trick involves a specific GCC interpretation of the specs on Lambdas in C++11. As such, it will (likely) become a defect report against the standard. This will lead to the trick no longer working in more recent version of GCC (it already doesn't work in 4.7).
See the comment thread below for some more details from Johanness
http://ideone.com/KytVv:
#include <iostream>
namespace detail {
template<bool C>
struct call_if { template<typename F> void operator<<(F) { } };
template<>
struct call_if<true> {
template<typename F>
void operator<<(F f) { f(); }
};
}
#define static_if(cond) detail::call_if<cond>() << [&]
template<bool C, typename T>
void f(T t) {
static_if(C) {
t.foo();
};
}
int main() {
f<false>(42);
}
Why not make the send implementation a policy of the sender class and use CRTP:
template<class Derived>
class SingleSenderPolicy
{
public:
template< class memFunc >
void callWrapperImpl(memFunc f, ...)
{
static_cast<Derived *>(this)->f(...);
}
};
template< class Derived >
class DoubleSenderPolicy
{
public:
template< class memFunc >
void callWrapperImpl(memFunc f, ...)
{
static_cast<Derived *>(this)->f(...);
static_cast<Derived *>(this)->f(...);
}
};
template< class SendPolicy>
class Sender : public SendPolicy< Sender >
{
public:
void sendMessage( ... )
{
// call the policy to do the sending, passing in a member function that
// acutally performs the action
callWrapperImpl( &Sender::sendMessageImpl, ... );
}
void doSomethingElse( ... )
{
callWrapperImpl( &Sender::doSomethingElseImpl, ... );
}
protected:
void sendMessageImpl(... )
{
// Do the sending here
}
void doSomethingElseImpl(... )
{
// Do the sending here
}
};
The public sendXXX functions in you class simply forward to the call wrapper, passing in a member function that implements the real functionality. This member function will be called according to the SendPolicy of the class. CRTP saves the use of bind to wrap the arguments and this pointer up with the member function to call.
With one function it doesn't really cut down on the amount of code, but if you have a lot of calls it could help.
Note: This code is a skeleton to provide a possible solution, it has not been compiled.
Note: Sender<DoubleSenderPolicy> and Sender<SingleSenderPolicy> are completely different types and do not share a dynamic inheritance relationship.
Most compilers do constant folding and dead code removal, so if you write a regular if statement like this:
enum SenderType { Single, Double };
template<SenderType T>
class Sender
{
void sendMessage(...)
{
// do stuff
if ( T == Single )
{
sendMessage(...);
}
}
};
The if branch will get removed when the code is generated.
The need for static if is when the statements would cause a compiler error. So say you had something like this(its somewhat psuedo code):
static if (it == random_access_iterator)
{
it += n;
}
Since you can't call += on non-random access iterators, then the code would always fail to compile with a regular if statement, even with dead code removal. Because the compiler still will check the syntax for before removing the code. When using static if the compiler will skip checking the syntax if the condition is not true.
std::string a("hello world");
// bool a = true;
if(std::is_same<std::string, decltype(a)>::value) {
std::string &la = *(std::string*)&a;
std::cout << "std::string " << la.c_str() << std::endl;
} else {
bool &la = *(bool*)&a;
std::cout << "other type" << std::endl;
}

C++ specialization, type_of or just typeid

I would like to know what is better to use in my situation and why. First of all I heard that using RTTI (typeid) is bad. Anyone could explain why? If I know exactly types what is wrong to compare them in a runtime? Furthermore is there any example how to use boost::type_of? I have found none searching through the mighty google :) Other solution for me is specialization, but I would neet to specialize at least 9 types of new method. Here is an example what I need:
I have this class
template<typename A, typename B, typename C>
class CFoo
{
void foo()
{
// Some chunk of code depends on old A type
}
}
So I need to rather check in typeid(what is I heard is BAD) and make these 3 realizations in example like:
void foo()
{
if (typeid(A) == typeid(CSomeClass)
// Do this chunk of code related to A type
else
if (typeid(B) == typeid(CSomeClass)
// Do this chunk of code related to B type
else
if (typeid(C) == typeid(CSomeClass)
// Do this chunk of code related to C type
}
So what is the best solution? I don't want to specialize for all A,B,C, because every type is has 3 specializations so I will get 9 methods or just this typeid check.
It's bad because
A, B and C are known at compile-time but you're using a runtime mechanism. If you invoke typeid the compiler will make sure to include metadata into the object files.
If you replace "Do this chunk of code related to A type" with actual code that makes use of CSomeClass's interface you'll see you won't be able to compile the code in case A!=CSomeClass and A having an incompatible interface. The compiler still tries to translate the code even though it is never run. (see example below)
What you normally do is factoring out the code into separate function templates or static member functions of classes that can be specialized.
Bad:
template<typename T>
void foo(T x) {
if (typeid(T)==typeid(int*)) {
*x = 23; // instantiation error: an int can't be dereferenced
} else {
cout << "haha\n";
}
}
int main() {
foo(42); // T=int --> instantiation error
}
Better:
template<typename T>
void foo(T x) {
cout << "haha\n";
}
void foo(int* x) {
*x = 23;
}
int main() {
foo(42); // fine, invokes foo<int>(int)
}
Cheers, s
Well generally solutions can be come up with without RTTI. It "can" show you haven't thought the design of the software out properly. THAT is bad. Sometimes RTTI can be a good thing though.
None-the-less there IS something odd in what you want to do. Could you not create an interim template designed something like as follows:
template< class T > class TypeWrapper
{
T t;
public:
void DoSomething()
{
}
};
then partially specialise for the functions you want to as follows:
template<> class TypeWrapper< CSomeClass >
{
CSomeClass c;
public:
void DoSomething()
{
c.DoThatThing();
}
};
Then in your class define above you would do something such as ...
template
class CFoo
{
TypeWrapper< A > a;
TypeWrapper< B > b;
TypeWrapper< C > c;
void foo()
{
a.DoSomething();
b.DoSomething();
c.DoSomething();
}
}
This way it only actually does something in the "DoSomething" call if it is going through the partially specialised template.
The problem lies in the code chunks you write for every specialization.
It doesn't matter if you write (lengthwise)
void foo()
{
if (typeid(A) == typeid(CSomeClass)
// Do this chunk of code related to A type
else
if (typeid(B) == typeid(CSomeClass)
// Do this chunk of code related to B type
else
if (typeid(C) == typeid(CSomeClass)
// Do this chunk of code related to C type
}
or
void foo()
{
A x;
foo_( x );
B y;
foo_( y );
C z;
foo_( z );
}
void foo_( CSomeClass1& ) {}
void foo_( CSomeClass2& ) {}
void foo_( CSomeClass3& ) {}
The upside of the second case is, when you add a class D, you get reminded by the compiler that there is an overload for foo_ missing which you have to write. This can be forgotten in the first variant.
I'm afraid this is not going to work in the first place. Those "chunks of code" have to be compilable even if the type is not CSomeClass.
I don't think type_of is going to help either (if it is the same as auto and decltype in C++0x).
I think you could extract those three chunks into separate functions and overload each for CSomeClass. (Edit: oh there are else if's. Then you might indeed need lots of overloads/specialization. What is this code for?)
Edit2: It appears that your code is hoping to do the equivalent of the following, where int is the special type:
#include <iostream>
template <class T>
bool one() {return false; }
template <>
bool one<int>() { std::cout << "one\n"; return true; }
template <class T>
bool two() {return false; }
template <>
bool two<int>() { std::cout << "two\n"; return true; }
template <class T>
bool three() {return false; }
template <>
bool three<int>() { std::cout << "three\n"; return true; }
template <class A, class B, class C>
struct X
{
void foo()
{
one<A>() || two<B>() || three<C>();
}
};
int main()
{
X<int, double, int>().foo(); //one
X<double, int, int>().foo(); //two
X<double, double, double>().foo(); //...
X<double, double, int>().foo(); //three
}
I think you've got your abstractions wrong somewhere.
I would try redefining A, B & C in terms of interfaces they need to expose (abstract base classes in C++ with pure virtual methods).
Templating allows basically duck-typing, but it sounds like CFoo knows too much about the A B & C classes.
typeid is bad because:
typeid can be expensive, bloats
binaries, carries around extra
information that shouldn't be
required.
Not all compilers support it
It's basically breaking the class hierarchy.
What I would recommend is refactoring: remove the templating, instead define interfaces for A, B & C, and make CFoo take those interfaces. That will force you to refactor the behaviour so the A, B & C are actually cohesive types.