Extraño error del compilador g++ al usar mi propia función plus() ("std::plus no es una función")

Recibo un extraño error de compilación de g++.

Dice "std::plus is not a function" para el siguiente código, aunque no estoy incluyendo <functional> y no estoy usando std donde ocurre el error.

Aquí está el código:

#include <iostream>

template<class T1, class T2, class T3>
struct MyStruct {
  T1 t1; T2 t2; T3 t3;
  MyStruct() {}
  MyStruct(T1 const& t1_, T2 const& t2_, T3 const& t3_)
    : t1(t1_), t2(t2_), t3(t3_) {}
};

template<class T1, class T2, class T3>
MyStruct<T1, T2, T3> plus(MyStruct<T1, T2, T3> const& x,
              MyStruct<T1, T2, T3> const& y) {
  // ...
}

int main() {
  typedef MyStruct<int, double, std::string> Struct;
  Struct x(2, 5.6, "bar");
  Struct y(6, 4.1, "foo");
  Struct result = plus(x, y);
}

Aquí está el error completo (ligeramente reformateado):

/usr/include/c++/4.2.1/bits/stl_function.h: In function 'int main()':
/usr/include/c++/4.2.1/bits/stl_function.h:134:
    error: 'template<class _Tp> struct std::plus' is not a function,
plus3.cc:13: error:
   conflict with 'template<class T1, class T2, class T3> 
     MyStruct<T1, T2, T3> plus(const MyStruct<T1, T2, T3>&, 
       const MyStruct<T1, T2, T3>&)'
plus3.cc:21: error:   in call to 'plus'

¿Alguien sabe por qué es esto y cómo evitar el error? Realmente me gustaría llamar a la función plus.

El error no ocurre cuando mi plus función no tiene 3 argumentos de plantilla, lo que tiene sentido después de ver la definición de std::plus:

  template <class _Tp>
    struct plus : public binary_function<_Tp, _Tp, _Tp>

Pero sigue siendo extraño porque std::plus Ni siquiera debería saberse en ese momento.

ACTUALIZACIÓN:

En respuesta a algunas respuestas, pegaré un código ligeramente modificado que también da el error. Mi plus la función está en namespace foo aquí, y se llama desde el mismo espacio de nombres, por lo que no debería haber ninguna necesidad de calificarlo usando foo:::

#include <string>

namespace foo {

template<class T1, class T2, class T3>
struct MyStruct {
  T1 t1; T2 t2; T3 t3;
  MyStruct() {}
  MyStruct(T1 const& t1_, T2 const& t2_, T3 const& t3_)
      : t1(t1_), t2(t2_), t3(t3_) {}
};

template<class T1, class T2, class T3>
MyStruct<T1, T2, T3> plus(MyStruct<T1, T2, T3> const& x,
                          MyStruct<T1, T2, T3> const& y) {
  // ...                                                                                                                        
}

template<class T1, class T2, class T3>
MyStruct<T1, T2, T3> bar(MyStruct<T1, T2, T3> const& x,
                         MyStruct<T1, T2, T3> const& y) {
  return plus(x, y);
}

} // end foo                                                                                                                    

int main() {
  typedef foo::MyStruct<int, double, std::string> Struct;
  Struct x(2, 5.6, "bar");
  Struct y(6, 4.1, "foo");
  Struct result = foo::bar(x, y);
}

preguntado el 22 de mayo de 12 a las 21:05

Esto se compila con gcc 4.5.1 (después de comentar la lista de inicializadores) -

@jrok: Interesante, entonces tal vez sea un error de g ++. También probé con g ++ 4.4.4 y recibo el mismo error. -

Recibo el mismo error aquí con g ++ 4.3.2, por lo que no es solo usted. Y cuando inserto using namespace std; solo por el gusto de hacerlo, solo entonces comienza a quejarse de que reference to ‘plus’ is ambiguous. ¡Así que sí sabe eso, al menos! problema interesante Pero podría ser solo un simple error del compilador, como sugiere el comentario de jrok. -

Su problema podría estar relacionado con esto: ¿Cuáles son las trampas de las ADL?. si abres encabezado de su implementación, verá que incluye bits/stl_function.h (probablemente usan std::less para el operador de cadena<) -

Como menciona jrok, en C ++ se permite que un encabezado estándar traiga cosas de otros encabezados estándar. Esto es diferente a C, donde no se permite que un encabezado traiga declaraciones de otros encabezados estándar. -

3 Respuestas

Es porque std::plus no es una función.

Su función plus está en el espacio de nombres global, por lo que debe hacer

Struct result = ::plus(x, y);

La razón por la que está tratando de usar std::plus es porque no fue explícito en la versión de plus que quería, por lo que el compilador usó Búsqueda de Koenig que encuentra más a través de sus argumentos.

contestado el 22 de mayo de 12 a las 21:05

Gracias por tu respuesta. Sin embargo, todavía es un misterio para mí, porque todavía recibo el error si mi plus está en su propio espacio de nombres, vea la ACTUALIZACIÓN que hice en mi publicación. Parece que necesitaría calificar el plus llamar con foo::plus aunque ya estoy en foo espacio de nombres También los 2 argumentos para plus tiene foo espacio de nombres, no en std espacio de nombres. - Frank

Hm, ¿y hay alguna manera de suprimir Koenig Lookup? - Señor lister

También Struct result = plus<int,double,std::string>(x, y); obras. - martín york

Está bien, pero todavía no veo una razón por la que debería ser obligatorio. - Frank

@MrLister: Sí. Sea explícito sobre qué función/tipo desea. - martín york

No obtendrá este error si coloca su función en un espacio de nombres diferente. Para esto están los espacios de nombres: puede tener el mismo símbolo/firma en diferentes espacios de nombres sin causar colisiones.

contestado el 22 de mayo de 12 a las 21:05

Intente especificar el espacio de nombres para usted plus() explícitamente

Struct result = ::plus(x, y);

Esto ayuda con gcc y no te obliga a poner tu plus() en un espacio de nombres diferente.

Loki Astari cuenta el resto

contestado el 22 de mayo de 12 a las 21:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.