2012-06-11 23 views
7

Cuando se intenta hacer un BOOST_CHECK_EQUAL (par, par), gcc no encuentra el operador de la ruta para el par, a pesar de declararlo. Lo curioso es que std :: out encuentra al operador.BOOST_CHECK_EQUAL con el par <int, int> y el operador personalizado <<

ostream& operator<<(ostream& s, const pair<int,int>& p) { 
    s << '<' << p.first << ',' << p.second << '>'; 
    return s; 
} 


BOOST_AUTO_TEST_CASE(works) 
{ 
    pair<int,int> expected(5, 5); 
    pair<int,int> actual (5, 5); 
    std::cout << expected << std::endl; 
    std::cout << actual << std::endl; 
    BOOST_CHECK(actual == expected); 
} 

BOOST_AUTO_TEST_CASE(no_work) 
{ 
    pair<int,int> expected(5, 5); 
    pair<int,int> actual (5, 5); 
    BOOST_CHECK_EQUAL(actual, expected); 
} 

ésto no compila con el error:

... instantiated from here 
../boost-atp/release/include/boost/test/test_tools.hpp:326:9: error: no match for ‘operator<<’ in ‘ostr << t’ 
+0

La nueva forma de definir * * su propia impresión de tipos personalizados se explica aquí: https://stackoverflow.com/a/44810846/1617295, y [esto es la documentación oficial] (http://www.boost.org/doc/libs/1_66_0/libs/test/doc/html/boost_test/test_output/test_tools_support_for_logging/testing_tool_output_disable.html) de esa función. – Raffi

+0

@ Raffi Esa pregunta parece un duplicado de esta, tiene menos detalles. Tal vez tiene sentido marcarlo como duplicado y mover su respuesta aquí para que no hagamos que los usuarios salten. Puedo aceptarlo también ¡Gracias! – nishantjr

Respuesta

7

Poner operator<< en std como Remus's answer es un comportamiento indefinido en el borrador de C++ 14 (sección N4296: 17.6.4.2.1). Boost proporciona un gancho (used by this answer) y se puede escribir:

namespace boost 
{ 
    namespace test_tools 
    { 
     template<typename T,typename U> 
     struct print_log_value<std::pair<T, U> > 
     { 
      void operator()(std::ostream& os, std::pair<T, U> const& pr) 
      { 
       os << "<" << std::get<0>(pr) << "," << std::get<1>(pr) << ">"; 
      } 
     }; 
    } 
} 

print_log_value es una plantilla así que si no está declarando un valor de plantilla como pair<T,U>, tendrá que escribir algo como:

template<> 
struct print_log_value<MyType>{ /* implementation here*/ }; 

Editar

Si está utilizando impulsar 1.59 o posterior, necesita utilizar el espacio de nombres boost::test_tools::tt_detail en su lugar. Es decir, el código tiene que empezar:

namespace boost 
{ 
    namespace test_tools 
    { 
     namespace tt_detail 
     { 
+0

¡Ah! ¡Eso es genial! Eso es mucho más limpio. – nishantjr

9

trate de poner la operator itself in the std namespace: Actualización

namespace std 
{ 
    ostream& operator<<(ostream& s, const pair<int,int>& p) { 
    s << '<' << p.first << ',' << p.second << '>'; 
    return s; 
    } 
} 

: tal vez esta es la razón por la ADL fails (al menos en llvm):

Just like before, unqualified lookup didn't find any declarations with the name operator<< . Unlike before, the argument types both contain class types: one of them is an instance of the class template type std::basic_ostream , and the other is the type ns::Data that we declared above. Therefore, ADL will look in the namespaces std and ns for an operator<< . Since one of the argument types was still dependent during the template definition, ADL isn't done until the template is instantiated during Use, which means that the operator<< we want it to find has already been declared. Unfortunately, it was declared in the global namespace, not in either of the namespaces that ADL will look in!

+0

No entiendo por qué ADL no se aplica dentro de BOOST_CHECK_EQUAL. ¿Impulsa Boost algo para evitar que eso suceda? – nishantjr

+0

@njr: Lo analicé hace algún tiempo, pero no encontré la causa raíz. Afaik gcc hace ADL, y también lo hace llvm. –

+1

Esto funciona para mí, pero parece ser un comportamiento indefinido (http://en.cppreference.com/w/cpp/language/extending_std). Mirando, descubrí la siguiente respuesta que ofrece una manera de evitar el comportamiento indefinido http://stackoverflow.com/a/17573165/309334 – Eponymous

0

Estaba buscando algo similar, una forma de personalizar la cadena de salida para imprimir enteros en hexadecimal. Inyectar un operador en el espacio de nombres std funcionaría, pero cada BOOST_CHECK en mi prueba se imprimiría en hexadecimal.

Así que inyecté algunos operadores personalizados en el espacio de nombres de impulso que pude controlar con algunos bools globales.

Ver mi respuesta aquí boost-check-fails-to-compile-operator-for-custom-types.