使用SFINAE解决过载模糊问题

时间:2015-03-09 09:40:07

标签: c++ templates c++11 sfinae ambiguity

我发现了类似的情况,但他们通常最终会按照我(我想)在这里做的事情做一些事情。

我希望能够使用一个或多个参数调用一个函数,显然,如果函数存在带有多个参数的重载,则无法在没有帮助的情况下推断出正确的版本。

由于我也指定了参数的数量,我认为这对于编译器推断正确的重载是足够的信息。 这似乎并非如此,我希望你能告诉我原因。

代码: 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;
}

简而言之,我试图使所有函数的参数数量不同于我提供的参数数量,但是通过SFINAE失败了。但似乎无论如何都要考虑它们,模糊性仍然存在。

1 个答案:

答案 0 :(得分:3)

不幸的是没有; SFINAE可用于在不同的函数模板定义之间进行选择,但不能在作为参数传递的函数重载之间进行选择。

这是因为在评估模板函数定义中的依赖类型并且SFINAE启动之前,必须将作为参数传递的重载函数解析为单个重载。

您可以通过创建n重载的模板定义来查看此内容,其中n - 1是您要处理的最大参数数量:

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... );
}

此处每个arg_count解析为一个call_my_function定义,因此特定call_my_function定义中没有关于传递arg_count的歧义。

一种可能的解决方案是手动或使用预处理器(例如使用Boost.Preprocessor)生成这些n重载。