使用 SFINAE 解决过载歧义
Resolve overload ambiguity with SFINAE
我发现了类似的案例,但他们通常最终会按照我(认为)我在这里所做的事情做一些事情。
我希望能够调用带有一个或多个参数的函数,显然,如果该函数存在带有多个参数的重载,则无法在没有帮助的情况下推导出正确的版本。
因为我也指定了参数的数量,所以我认为这足以让编译器推断出正确的重载。
事实并非如此,我希望你能告诉我为什么。
代码:
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 使所有参数计数与我提供的参数数量不同的函数失败。但似乎无论如何都在考虑它们,并且仍然存在歧义。
很遗憾没有; 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
重载。
我发现了类似的案例,但他们通常最终会按照我(认为)我在这里所做的事情做一些事情。
我希望能够调用带有一个或多个参数的函数,显然,如果该函数存在带有多个参数的重载,则无法在没有帮助的情况下推导出正确的版本。
因为我也指定了参数的数量,所以我认为这足以让编译器推断出正确的重载。 事实并非如此,我希望你能告诉我为什么。
代码: 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 使所有参数计数与我提供的参数数量不同的函数失败。但似乎无论如何都在考虑它们,并且仍然存在歧义。
很遗憾没有; 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
重载。