2011-05-31 14 views
7

posibles duplicados:
Why can't my C++ compiler deduce template argument for boost function?
Isn't the template argument (the signature) of std::function part of its type?conversiones implícitas con std :: función

Tengo el siguiente:

#include <functional> 

void Foo(std::function<void()> ); 
void Foo(std::function<void(int)>); 
void Bar(); 

int main() 
{ 
    Foo(Bar);  // Error: ambiguous 
    Foo([](){}); // Error: ambiguous 

    Foo(std::function<void()>(Bar )); // Ok 
    Foo(std::function<void()>([](){})); // Ok 
} 

¿Puedo hacer las dos primeras líneas en main() trabajo sin el estilo de función cas t en las últimas dos líneas? Tal vez con una solución std :: enable_if?

Respuesta

4

Cualquier llamada a foo con un parámetro que no es precisamente una de std::function<void()> y std::function<void(int)> dará lugar a una sobrecarga sin resolver. Incluso cosas tontas como Foo(1) o Foo("abc"). Esto se debe a que los constructores de std::function tienen plantillas y aceptan cualquier tipo. std::function<void()>(1) fallará en la instanciación, pero la resolución de sobrecarga ocurre antes de la creación de instancias.

Así que no, debe proporcionar una coincidencia exacta con una de las funciones, de una forma u otra. Se pueden introducir otros casos sobrecargados de Foo, como

void Foo(void (*)()); 
void Foo(void (*)(int)); 

y esto se traducirá en una mejor adaptación y la ambigüedad será no más.

3

Es posible utilizar SFINAE para que esto funcione correctamente, en C++ 0x. Sin embargo, los errores de SFINAE de MSVC hacen que sea imposible para ellos, hasta donde yo sé, y los implementadores de la biblioteca de GCC no parecen haber notado, por lo que lamentablemente esto no funciona.

También podría intentar algún tipo de make_function, supongo. Disculpe mis plantillas variadic, ha pasado un tiempo.

template<typename T> struct function_proxy { 
    T f; 
    template<typename Ret, typename... T> operator std::enable_if<std::is_same<Ret, decltype(f(std::declval<T>()...))>::value, std::function<Ret(T...)>>::type() { 
     return std::function<Ret(T...)>(f); 
    } 
}; 
template<typename T> function_proxy<T> make_function(T&& t) { 
    return function_proxy { std::forward<T>(t); } 
} 
Cuestiones relacionadas