Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ std::function cannot find correct overload

Tags:

c++

c++11

lambda

Consider the following case:

void Set(const std::function<void(int)> &fn);
void Set(const std::function<void(int, int)> &fn);

Now calling the function with

Set([](int a) {
    //...
});

Gives "ambiguous call to overloaded function" error. I am using Visual Studio 2010. Is there a work around or another method to achieve something similar. I cannot use templates, because these functions are stored for later use because I cannot determine the number of parameters in that case. If you ask I can submit more details.

like image 844
Cem Kalyoncu Avatar asked Nov 08 '11 16:11

Cem Kalyoncu


People also ask

How do you overload a function in C++?

You overload a function name f by declaring more than one function with the name f in the same scope. The declarations of f must differ from each other by the types and/or the number of arguments in the argument list.

Which function in C Cannot be overloaded?

2) Member function declarations with the same name and the name parameter-type-list cannot be overloaded if any of them is a static member function declaration.

Is there function overload in C?

This feature is present in most of the Object Oriented Languages such as C++ and Java. But C doesn't support this feature not because of OOP, but rather because the compiler doesn't support it (except you can use _Generic).

Can we overload functions in C++? * Yes?

Function overloading in C++ can be used to enhance code readability. To save compile time and memory, we can use this function overloading concept.


2 Answers

I would suggest this solution. It should work with lambdas as well as with function-objects. It can be extended to make it work for function pointer as well (just go through the link provided at the bottom)

Framework:

template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
{
    enum { arity = sizeof...(Args) };
};

template<typename Functor, size_t NArgs>
struct count_arg : std::enable_if<function_traits<Functor>::arity==NArgs, int>
{};

Usage:

template<typename Functor>
typename count_arg<Functor, 1>::type Set(Functor f) 
{
    std::function<void(int)> fn = f;
    std::cout << "f with one argument" << std::endl;
}

template<typename Functor>
typename count_arg<Functor, 2>::type Set(Functor f)
{
    std::function<void(int, int)> fn = f;
    std::cout << "f with two arguments" << std::endl;
}

int main() {
        Set([](int a){});
        Set([](int a, int b){});
        return 0;
}

Output:

f with one argument
f with two arguments

I took some help from the accepted answer of this topic:

  • Is it possible to figure out the parameter type and return type of a lambda?

Work around for Visual Studio 2010

Since Microsoft Visual Studio 2010 doesn't support variadic templates, then the framework-part can be implemented as:

template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};

template <typename C, typename R, typename T0>
struct function_traits<R(C::*)(T0) const> { enum { arity = 1 }; };

template <typename C, typename R, typename T0, typename T1>
struct function_traits<R(C::*)(T0,T1) const> { enum { arity = 2 }; };

template <typename C, typename R, typename T0, typename T1, typename T2>
struct function_traits<R(C::*)(T0,T1,T2) const> { enum { arity = 3 }; };

//this is same as before 
template<typename Functor, size_t NArgs, typename ReturnType=void>
struct count_arg : std::enable_if<function_traits<Functor>::arity==NArgs, ReturnType>
{};

EDIT
Now this code supports any return type.

like image 107
Nawaz Avatar answered Oct 04 '22 04:10

Nawaz


I suggest:

  void Set(void(*f)(int, int))
  { 
      std::function<void(int,int)> wrap(f);
      // ...
  }

  void Set(void(*f)(int))
  { 
      std::function<void(int)> wrap(f);
      // ...
  }
like image 36
sehe Avatar answered Oct 04 '22 02:10

sehe