Resolve overload ambiguity with SFINAE

雨燕双飞 提交于 2019-12-10 10:36:52

问题


I've found similar cases, but they usually ended up doing something along the lines of what I (think) I'm doing here.

I want to be able to call a function with one or more parameters, obviously, if the function exists with overloads with multiple parameters, the correct version cannot be deduced without help.

As I am specifying the number of arguments as well, I figured this would be enough information for the compiler to deduce the correct overload. This doesn't seem to be the case and I hope you may be able to show me why.

the code: http://coliru.stacked-crooked.com/a/5e6fd8d5418eee3c

#include <iostream>
#include <type_traits>
#include <functional>

template < typename R, typename... A, typename... Args >
typename std::enable_if< sizeof...( A ) == sizeof...( Args ), R >::type
call_my_function( R(*func)(A...), Args ...a )
{
    return func( a... );
}

int arg_count() { return 0; }
int arg_count(int) { return 1; }
int arg_count(int,int) { return 2; }

int main()
{
    std::cout << call_my_function( arg_count, 0 ) << std::endl;
    return 0;
}

In short, I tried to have all functions which have a different argument count than the number of arguments I supplied, fail by means of SFINAE. But it seems they are considered anyway and the ambiguity remains.


回答1:


Unfortunately not; SFINAE can be used for selecting between different function template definitions, but not between function overloads passed as an argument.

This is because an overloaded function passed as an argument must be resolved to a single overload before dependent types in the template function definition are evaluated and SFINAE kicks in.

You can see this by creating n overloaded template definitions, where n - 1 is the maximum number of arguments you want to handle:

template < typename R, typename... Args >
typename std::enable_if< 0 == sizeof...( Args ), R >::type
call_my_function( R(*func)(), Args ...a )
{
    return func( a... );
}

template < typename R, typename A1, typename... Args >
typename std::enable_if< 1 == sizeof...( Args ), R >::type
call_my_function( R(*func)(A1), Args ...a )
{
    return func( a... );
}

template < typename R, typename A1, typename A2, typename... Args >
typename std::enable_if< 2 == sizeof...( Args ), R >::type
call_my_function( R(*func)(A1, A2), Args ...a )
{
    return func( a... );
}

Here each arg_count resolves to exactly one call_my_function definition, so there is no ambiguity within a particular call_my_function definition as to which arg_count was passed.

A possible solution would be to generate these n overloads either manually or using the preprocessor (e.g. using Boost.Preprocessor).



来源:https://stackoverflow.com/questions/28938839/resolve-overload-ambiguity-with-sfinae

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!