Search code examples
c++performancestaticc++11static-if

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.


Solution

  • 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);
    }