I want to have some compile time if. But I can't just put if statement because compiler will check both branches, and one of branches may be invalid (call not existing in this case function, etc..).
In other words I want #ifdef but in templates. Consider helper/wrapper of this. So, I write the following templated class, which expect bool argument. "true" specialization call one function,  "false" - another:
#define MAKE_IF(c_name, fn1, fn2)\
template<bool select, class DUMMY = void>\
struct c_name{\
};        \
\
template<class DUMMY>\
struct c_name<true, DUMMY>{\
  template<typename SELF, typename ...Args>\
  static auto fire(SELF &&self, Args &&...args)-> decltype( self.fn1(std::forward<Args>(args)...) ){\
    return self.fn1( std::forward<Args>(args)... );\
  }\
};\
\
template<class DUMMY>\
struct c_name<false, DUMMY>{\
  template<typename SELF, typename ...Args>\
  static auto fire(SELF &&self, Args &&...args) -> decltype( self.fn2(std::forward<Args>(args)...) ) {\
    return self.fn2( std::forward<Args>(args)...);\
  }\
};
/// Usage:
MAKE_IF(selector, fn1, fn2 )
selector<do_it>::fire(*this);
All good, all work. But I want to get rid of this #defines, so I make the following thing (lambda based):
template<bool select, class DUMMY = void>
struct CONDITION_HELPER{};        
template<class DUMMY>
struct CONDITION_HELPER<true, DUMMY>{
  template<class FN1, class FN2>
  static auto fire(FN1 &&fn1, FN2 &&) -> decltype( fn1() ){
    return fn1();
  }
};        
template<class DUMMY>
struct CONDITION_HELPER<false, DUMMY>{
  template<class FN1, class FN2>
  static auto fire(FN1 &&, FN2 &&fn2) -> decltype( fn2() ){
    return fn2();
  }
};        
template<bool first, class FN1, class FN2>
auto if_else(FN1 &&fn1, FN2 &&fn2) -> decltype(
    CONDITION_HELPER<first>::fire(
            std::forward<FN1>(fn1),
            std::forward<FN2>(fn2)
        )   
    ){
    return CONDITION_HELPER<first>::fire(
        std::forward<FN1>(fn1),
        std::forward<FN2>(fn2)
    );
}
 //Usage:
 if_else<do_it>(
                    [&]{ return fn1(data); },
                    [&]{ return fn2(data); }
                );
And this does not work. On the line with the lambdas I get the error
main.cpp:111:37: error: non-const lvalue reference to type 'B' cannot bind to a value of unrelated type 'A'
                [&]{ return fn1(data); },
Complete code:
 
    