2012-05-23 8 views
16

¿Cómo puedo enlazar a una función que toma argumentos predeterminados, sin especificar los argumentos predeterminados y luego llamar sin ningún argumento?¿Puedo vincularme a una función que toma argumentos predeterminados y luego llamarlos?

void foo(int a, int b = 23) { 
    std::cout << a << " " << b << std::endl; 
} 

int main() { 
    auto f = std::bind(foo, 23, 34); // works 
    f(); 


    auto g = std::bind(foo, 23); // doesn't work 
    g(); 

    using std::placeholders::_1; 
    auto h = std::bind(foo, 23, _1); // doesn't work either 
    h(); 

} 
+1

Definir "no funciona". El código se compila si le da diferentes nombres a las variables. –

+0

¿por qué sigues reasignando a f? – 111111

+0

@ R.MartinhoFernandes sí lo siento, el ejemplo estaba incompleto. código actualizado – inf

Respuesta

20

Básicamente, cada vez que escribir foo(x) el compilador traduce a foo(x, 23);. Solo funciona si realmente tiene una llamada directa con el nombre de la función. No puede, por ejemplo, asignar &foo a void(*)(int), porque la firma de la función es void(int, int). Los parámetros predeterminados no tienen parte en la firma. Y si lo asigna a una variable void(*)(int, int), la información sobre el parámetro predeterminado se pierde: no puede aprovechar el parámetro predeterminado a través de esa variable. std::bind almacena un void(*)(int, int) en algún punto de sus entrañas, y pierde así la información de parámetros predeterminada.

En C++ no hay forma de obtener el valor predeterminado de un parámetro desde fuera de la función, por lo que tiene que proporcionar manualmente el valor predeterminado cuando se vincula.

+0

gran fondo, gracias. – inf

8

Creo que podrías simular el comportamiento que deseas con una lambda.

Algo a lo largo de las líneas de este:

auto g = [](){ foo(23); }; 

EDIT: sólo nos registramos, y parece funcionar bien: http://ideone.com/SPSvi

0

Tengo dos soluciones:

1 - Puede sobrecargar foo () y hacer que llame al original con los valores predeterminados:

void foo(int a, int b) 
{ 
    std::cout << a << " " << b << std::endl; 
} 

inline void foo(int a) 
{ 
    foo(a, 23); 
} 

2 - Se puede usar una variable estática por defecto y luego usarlo en el proceso de unión:

static int foo_default_b = 23; 
void foo(int a, int b = foo_default_b) 
{ 
    std::cout << a << " " << b << std::endl; 
} 

auto g = std::bind(foo, 23, foo_default_b); 
g(); 
0

This answer no está de acuerdo con la respuesta R. Martinho Fernandes. Si lo necesitas puedes usar boost::bind de obligar a los parámetros por defecto, sólo tiene que poner marcadores de posición en, como tan:

boost::bind<void (int, int)>(foo, _1, _2)(12); 

Para ello, será foo(12, 23), como se esperaba. Aunque no probé este código específico, hice algo similar en mi código basado en la respuesta vinculada anteriormente, y funciona en gcc 4.8.5.

Hmm, Me acabo de dar cuenta de que esto es preguntar acerca de std::bind, no boost::bind. No sé qué diferencias hay, si hay alguna.

Cuestiones relacionadas