BOOST_CHECK_EQUAL с парой <int, int> и пользовательским оператором <<

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

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’
 nishantjr15 февр. 2018 г., 07:03
@Raffi Этот вопрос выглядит как дубликат этого вопроса, имеет меньше деталей. Может быть, имеет смысл пометить его как дубликат и переместить свой ответ сюда, чтобы мы не заставляли пользователей прыгать? Я тоже могу это принять. Спасибо!
 Raffi14 февр. 2018 г., 20:49
new способ определения собственной печати для пользовательских типов объясняется здесь:stackoverflow.com/a/44810846/1617295 , а такжеthis is the official documentation этой функции.

Ответы на вопрос(3)

Решение Вопроса

operator<< вstd лайкОтвет Ремуса является неопределенным поведением в черновике C ++ 14 (раздел N4296: 17.6.4.2.1). Boost обеспечивает крючок (используется этим ответом) и вы можете написать:

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*/ };

Edit

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

namespace boost
{
    namespace test_tools
    {
        namespace tt_detail
        {
 nishantjr30 нояб. 2015 г., 05:43
Ах! Это здорово! Это намного чище.

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

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

Смотрите мой ответ здесьповышение-чек-терпит неудачу к компиляции оператора-для-пользовательских-типов.

сам оператор в пространстве имен std:

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

Обновление: возможно, поэтомуADL не работает (хотя бы на 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!

 27 нояб. 2015 г., 21:34
Good news: Данный пример отсутствует в проекте стандарта C ++ 14 (раздел N4296: 17.6.4.2.1).Bad news: формулировка стандарта похожа на ту, которую вы цитировали. Единственными вещами, перечисленными как разрешенные в стандарте, являются шаблонные специализации.ostream& operator<<(ostream&, pair<int,int>) это не специализация шаблона, это перегрузка функции.
 11 июн. 2012 г., 10:35
@njr: я изучал это некоторое время назад, но не нашел основную причину. Afaik GCC делает ADL, и поэтому делает llvm.
 nishantjr11 июн. 2012 г., 10:27
Я не понимаю, почему ADL не применяется в BOOST_CHECK_EQUAL. Boost делает что-нибудь, чтобы остановить это?
 27 нояб. 2015 г., 21:36
Формулировка такова: поведение программы на C ++ не определено, если она добавляет объявления или определения в пространство имен std или в пространство имен в пространстве имен std, если не указано иное. Программа может добавить специализацию шаблона для любого стандартного шаблона библиотеки в пространство имен std, только если объявление зависит от типа, определенного пользователем, и специализация соответствует требованиям стандартной библиотеки для исходного шаблона и явно не запрещена.
 27 нояб. 2015 г., 20:58
Это работает для меня, но это, кажется, неопределенное поведение (en.cppreference.com/w/cpp/language/extending_std ). Глядя, я обнаружил следующий ответ, который дает способ избежать неопределенного поведенияstackoverflow.com/a/17573165/309334

Ваш ответ на вопрос