  #include <utility>
  #include <type_traits>
  #include <cstddef>
  #include <iostream>
  
  #define CONCAT2( a, b ) a##b
  #define CONCAT( a, b ) CONCAT2(a,b)
  
  // SFINAE helper boilerplate:
  template<typename T> struct is_type:std::true_type {};
  template<std::size_t n> struct secret_enum { enum class type {}; };
  template<bool b, std::size_t n>
  using EnableIf = typename std::enable_if< b, typename secret_enum<n>::type >::type;

  // Macro that takes a srcF name and a dstF name and an integer N and
  // forwards arguments matching dstF's signature.  An integer N must be
  // passed in with a distinct value for each srcF of the same name:
  #define FORWARD_FUNC( srcF, dstF, N ) \
  template< typename... Args, \
    EnableIf< is_type< \
      decltype( dstF ( std::forward<Args>(std::declval<Args>())... )) \
    >::value , N >... > \
  auto srcF ( Args&&... args ) \
    -> decltype(dstF ( std::forward<Args>(args)... )) \
  { \
    dstF ( std::forward<Args>(args)... ); \
  }

  #define MAKE_FUNCS( f ) \
    FORWARD_FUNC( f, ::f, 0 ) \
    FORWARD_FUNC( f, :: CONCAT( f, s ), 1 )
    
void add( double* a, double* b, double* c) {*a = *b+*c;}
void adds( float* a, float* b, float* c) {*a = *b+*c;}
namespace math {
    MAKE_FUNCS(add)
}
int main() {
    double a, b = 2, c = 3;
    float af, bf = 3, cf = 5;
    math::add( &a, &b, &c );
    math::add( &af, &bf, &cf );
    std::cout << a << "=" << b << "+" << c << "\n";
    std::cout << af << "=" << bf << "+" << cf << "\n";
}