2012-06-11 7 views
7

При попытке выполнить BOOST_CHECK_EQUAL (пара, пара) gcc не находит оператора потока для пары, что бы его не объявить. Самое смешное, что std :: out находит оператора.BOOST_CHECK_EQUAL с парой <int, int> и пользовательским оператором <<

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); 
} 

Это оленья кожа компиляции с ошибкой:

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

The * новый * способ определения собственной печати пользовательских типов объясняются здесь: https://stackoverflow.com/a/44810846/1617295, и [это официальную документацию] (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) этой функции. – Raffi

+0

@ Raffi Этот вопрос выглядит как дубликат этого, имеет меньше деталей. Может быть, имеет смысл отметить это как дубликат и переместить свой ответ здесь, чтобы мы не заставляли пользователей прыгать? Я тоже могу это принять. Благодаря! – nishantjr

ответ

7

Ввод operator<< в std как Remus's answer - это неопределенное поведение в проекте C++ 14 (раздел N4296: 17.6.4.2.1). Повышение обеспечивает крюк (used by this answer), и вы можете написать:

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 шаблон, так что если вы не объявлять шаблонный значение как pair<T,U>, вам нужно будет написать что-то вроде:

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

Редактировать

Если вы используете boost 1.59 или новее, вам нужно вместо этого использовать пространство имен boost::test_tools::tt_detail. То есть, код должен начать:

namespace boost 
{ 
    namespace test_tools 
    { 
     namespace tt_detail 
     { 
+0

А! Замечательно! Это намного чище. – nishantjr

9

Попробуйте поставить operator itself in the std namespace: Обновление

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

: возможно, именно поэтому ADL fails (по крайней мере, на 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

Я не понимаю, почему ADL не применяется в BOOST_CHECK_EQUAL. Неужели Boost что-то делает, чтобы это не произошло? – nishantjr

+0

@njr: Я изучил его некоторое время назад, но не нашел первопричины. Afaik gcc делает ADL, а также llvm. –

+1

Это работает для меня, но, похоже, это неопределенное поведение (http://en.cppreference.com/w/cpp/language/extending_std). Глядя, я обнаружил следующий ответ, который дает возможность избежать неопределенного поведения. Http://stackoverflow.com/a/17573165/309334 – Eponymous

0

Я искал что-то подобное, способ настроить выходную строку для печати целых чисел в шестнадцатеричном формате. Ввод оператора в пространство имен std будет работать, но каждый BOOST_CHECK в моем тесте будет напечатан в шестнадцатеричном виде.

Поэтому я ввел некоторые пользовательские операторы в пространстве имен boost, которые я мог бы контролировать с помощью некоторых глобальных bools.

См. Мой ответ здесь boost-check-fails-to-compile-operator-for-custom-types.