Problem in short:
How could one implement static if
functionality, proposed in c++11, in plain c++ ?
History and original prob
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.
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.
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;
}