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.
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.
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.
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).
Function overloading in C++ can be used to enhance code readability. To save compile time and memory, we can use this function overloading concept.
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:
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.
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);
// ...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With