Tom de Geus
Tom de Geus

Reputation: 5965

Overload local lambda function

I have a function which is almost the same for double and int input. I have therefore overloaded the function for the two types. Unfortunately, at the core, there is a difference between the double and the int variants. Currently, I depend on an overloaded 'core' function for this. To enhance readability I would like to have the overloaded (very short) core functions as part of the function itself, for example using a lambda function.

This example below summarizes my current layout (of course the real code is a bit more involved).

#include <iostream>
#include <cstdlib>

double func_core ( double a, double b ) {
  return a*b;
}

int func_core ( int a, int b ) {
  if ( a==b )
    return 1.;
  else
    return 0.;
}

template <class T> T func ( T a, T b ) {
  return func_core(a,b);
}

int main ( void ) {
  std::cout << func(10 ,20 ) << std::endl;
  std::cout << func(10.,20.) << std::endl;
  return 0;
}

For reasons beyond this example I use C++14 (consistent with this I compiled this example using clang++ -std=c++14 example.cpp).

Now, I want to get rid of the core-function (func_core in this example) because it reduces the readability of my code. Ideally I want to use a lambda function that is overloaded within the function itself. I have summarized my thoughts in the example below (that is not working).

template <class T> T func ( T a, T b ) {
  if ( sizeof(T)==sizeof(int) )
    auto func_core = [](int a,int b){ if (a==b) return 1.; else return 0.; };
  else if ( sizeof(T)==sizeof(double) )
    auto func_core = [](double a,double b){ return a*b; };
  else
    throw std::runtime_error("Overload type not allowed");

  return func_core(a,b);
}

Can this be done? Or am I over-stretching?

Upvotes: 2

Views: 186

Answers (2)

amchacon
amchacon

Reputation: 1961

You can use type traits

template <class T> T func ( T a, T b ) {
    if (std::is_integral<T>::value)
        if (a==b) return 1;
        else return 0;
    else if (std::is_floating_point<T>::value)
        return a*b;
    else
        throw std::runtime_error("Overload type not allowed");
}

Anyway, i think that best way is avoid lambdas and use normal function overloading.

Upvotes: 2

Dimitrios Bouzas
Dimitrios Bouzas

Reputation: 42909

Unfortunately, either with C++11 or C++14 you'd to play with beasts like SFINAE or overload resolution to acomplish what you want.

In C++17 however you could use constexpr if and merge all the desired functionality into one function template as:

template<typename T>
 T func (T const &a, T const &b) {
  if constexpr(std::is_integral<T>::value)
    return (a == b)? 1 : 0;
  else
    return a * b;
}

Live Demo

Upvotes: 5

Related Questions