2015-03-09 3 views
2

Я нашел похожие случаи, но они обычно делали что-то вроде того, что я (думаю) я здесь делаю.Устранение неоднозначности перегрузки с помощью 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. Но, похоже, их все равно считают, и двусмысленность остается.

+0

Имя 'args_count' само по себе является неоднозначным, поскольку нет никакой информации о том, какую перегрузку он мог бы ссылаться. Вы можете использовать бросок или заставить свои функции выполнять правильную перегрузку функции, но это не может произойти в общем случае. – 0x499602D2

ответ

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.

Возможным решением было бы сгенерировать эти перегрузки n либо вручную, либо с использованием препроцессора (например, с использованием Boost.Preprocessor).