2011-10-19 11 views
14

que tienen una estructura como esta:Usando bind1st por un método que toma el argumento por referencia

struct A { 
    void i(int i) {} 
    void s(string const &s) {} 
}; 

Ahora cuando intento esto:

bind1st(mem_fun(&A::i), &a)(0); 
bind1st(mem_fun(&A::s), &a)(""); 

La primera línea compila bien, pero la segunda genera un error:

c:\program files (x86)\microsoft visual studio 10.0\vc\include\xfunctional(299): error C2535: 'void std::binder1st<_Fn2>::operator()(const std::basic_string<_Elem,_Traits,_Ax> &) const' : member function already defined or declared 
      with 
      [ 
       _Fn2=std::mem_fun1_t<void,A,const std::string &>, 
       _Elem=char, 
       _Traits=std::char_traits<char>, 
       _Ax=std::allocator<char> 
      ] 
      c:\program files (x86)\microsoft visual studio 10.0\vc\include\xfunctional(293) : see declaration of 'std::binder1st<_Fn2>::operator()' 
      with 
      [ 
       _Fn2=std::mem_fun1_t<void,A,const std::string &> 
      ] 
      c:\work\sources\exception\test\exception\main.cpp(33) : see reference to class template instantiation 'std::binder1st<_Fn2>' being compiled 
      with 
      [ 
       _Fn2=std::mem_fun1_t<void,A,const std::string &> 
      ] 

¿Cuál podría ser el problema? ¿Cómo podría solucionarlo?

Editar:

parece que cualquier argumento de referencia es un problema. Entonces, si cambio el método i al void i(int &i) {}, aparece un error similar.

+0

Dado que estamos en el año 2011 y tiene 11 C++ es posible que desee echar un vistazo a C++ '11s std :: bind' o' boost :: bind 'que hace que esas cosas órdenes de magnitud sean más fáciles de manejar. – PlasmaHH

+1

@PlasmaHH: Desafortunadamente, no puedo usar C++ 11 en este proyecto. –

+0

Y también no 'boost :: bind'? – PlasmaHH

Respuesta

10

std :: bind1st y std :: bind2nd no aceptan los funtores que toman los argumentos de referencia, porque ellos mismos hacen referencias a estos argumentos. Puede

  1. punteros utilizar para sus entradas de la función en lugar de referencias
  2. uso impulso :: ates
  3. aceptar el costo de rendimiento de la copia de la cadena
6

El problema es un defecto en la especificación de la biblioteca.

Tome un vistazo a este informe de errores con gcc y la discusión resultante: Bug 37811 - bind1st fails on mem_fun with reference argument

C++ 03 carecían de las instalaciones para construir una biblioteca de enlace perfecto. Este problema se corrigió en C++ 11 con reenvío perfecto y std :: bind.

0

Mira esta post eran los requisitos de los parámetros de la plantilla son explicados. Como ya asumió, la referencia a std :: string es el problema. No es un parámetro de plantilla válido.

+1

Si bien esto es cierto, el tipo de argumento de la función se transporta de mem_fun a bind1st a través del type_def del tipo first_argument_type, y una referencia es un typedef válido. Entonces std :: bind1st * could * teóricamente acepta referencias, pero se implementa de forma diferente (y esta implementación es obligatoria según el estándar, IIRC). – thiton

0

Cambiar las referencias de punteros

#include <functional> 
#include <string> 

struct A { 
    void i(int i) {} 
    void s(const std::string *s) {} 
}; 


int main(void) 
{ 
    A a; 
    std::bind1st(std::mem_fun(&A::i), &a)(0); 
    const std::string s(""); 
    std::bind1st(std::mem_fun(&A::s), &a)(&s); 
} 
Cuestiones relacionadas