Как можно разрешить передачу вектора в INFO (), CAPTURE (), WARN () и т. Д., Избегая при этом незаконного расширения пространства имен std?

В Catch Unit Test v1.8.1, с gcc 6.2.0, я пытаюсь удобно выводить содержимое вектора при сбое теста, передавая вектор в INFO(...) или же CAPTURE(...), Для этого я перегружаю оператор вставки потока:

#include <Catch/single_include/catch.hpp>
#include <vector>
#include <iostream>

#define THIS_WORKS_BUT_EXTENDING_NAMESPACE_STD_IS_ILLEGAL
#ifdef THIS_WORKS_BUT_EXTENDING_NAMESPACE_STD_IS_ILLEGAL
namespace std {
#endif

std::ostream& operator << ( std::ostream& os, const std::vector<int>& v ) {
for ( const auto& e : v ) {
os << e << " ";
}
return os;
}

#ifdef THIS_WORKS_BUT_EXTENDING_NAMESPACE_STD_IS_ILLEGAL
} //namespace std
#endif

int some_operation_on_vector( const std::vector<int>& v ) {
return 1;
}

SCENARIO( "some scenario" )
{
GIVEN( "a vector" )
{
const auto the_vector = std::vector<int>{ 1, 2, 3, 4, 5 };

WHEN( "some result is calculated from the vector" )
{
const auto actual_result = some_operation_on_vector( the_vector );

THEN( "the result should be correct.  If not, print out the vector." )
{
const auto expected_result = 0;

CAPTURE( the_vector ); // <--------
//^^^^
//How do I legally make this work?

REQUIRE( expected_result == actual_result );
}
}
}
}

Если я (незаконно) продлю std Пространство имен, как указано выше, затем он работает, и я вижу желаемый результат:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
catchtestexample is a Catch v1.8.1 host application.
Run with -? for options

-------------------------------------------------------------------------------
Scenario: some scenario
Given: a vector
When: some result is calculated from the vector
Then: the result should be correct.  If not, print out the vector.
-------------------------------------------------------------------------------
ExampleTest.cpp:91
...............................................................................

ExampleTest.cpp:95: FAILED:
REQUIRE( expected_result == actual_result )
with expansion:
0 == 1
with message:
the_vector := 1 2 3 4 5

===============================================================================
test cases: 1 | 1 failed
assertions: 1 | 1 failed

Но чтобы попытаться быть законным, когда я пытаюсь operator << перегрузка из std пространство имен и в глобальное пространство имен (путем комментирования #define THIS_WORKS_BUT_EXTENDING_NAMESPACE_STD_IS_ILLEGAL) код не компилируется из-за передачи вектора в CAPTURE() макро.

В соответствии с Поймать документы, Я пытался заменить operator << перегрузка с Catch::toString перегрузка:

#include <string>
#include <sstream>

namespace Catch {
std::string toString( const std::vector<int>& v ) {
std::ostringstream ss{};
for ( const auto& e : v ) {
ss << e << " ";
}
return ss.str();
}
}

или с Catch::StringMaker специализация:

#include <string>
#include <sstream>

namespace Catch {
template<> struct StringMaker<std::vector<int>> {
static std::string convert( const std::vector<int>& v ) {
std::ostringstream ss{};
for ( const auto& e : v ) {
ss << e << " ";
}
return ss.str();
}
};
}

но в любом случае тест по-прежнему не компилируется из-за передачи вектора в CAPTURE() макро.

Документы Catch говорят, чтобы поставить operator << перегрузка в то же пространство имен, что и ваш тип, но std::vector это не мой тип, и положить эту перегрузку в пространство имен std незаконно

Но единственный способ, которым я смог найти, чтобы получить CAPTURE() (или же INFO(), или же WARN()и т. д.) принять std::vector аргумент в том, чтобы незаконно поставить operator << перегрузка в пространство имен std,

Есть ли правильный, законный способ сделать это?

0

Решение

Я думаю, что нашел ответ, который работает. (РЕДАКТИРОВАТЬ: см. другой ответ для лучших решений.)

Вместо того, чтобы положить operator << перегрузка в std пространство имен, поместив его в Catch Пространство имен компилируется и дает желаемое поведение:

namespace Catch {

std::ostream& operator << ( std::ostream& os, const std::vector<int>& v ) {
for ( const auto& e : v ) {
os << e << " ";
}
return os;
}

}

Поймать документы скажи поставить operator << Перегрузите в то же пространство имен, что и ваш тип:

оператор << перегрузка для std :: ostream

Это стандартный способ преобразования строк в C ++, и есть вероятность, что вы уже можете предоставить его для своих собственных целей. Если вы не знакомы с этой идиомой, то она предполагает написание бесплатной функции вида:

   std::ostream& operator << ( std::ostream& os, T const& value ) {
os << convertMyTypeToString( value );
return os;
}

(где T это твой тип и convertMyTypeToString здесь вы будете писать любой код, необходимый для того, чтобы ваш тип печатался (это не обязательно должно быть в другой функции).

Вы должны поместить эту функцию в то же пространство имен, что и ваш тип. [Акцент мой]

В качестве альтернативы вы можете написать его как функцию-член:

   std::ostream& T::operator << ( std::ostream& os ) const {
os << convertMyTypeToString( *this );
return os;
}

Но так как std :: vector не мой типа, и он живет в пространстве имен stdЯ не могу сделать то, что говорят документы.

Так можно ли ставить operator << перегрузка в Catch пространство имен вместо? Это работает, но это нормально? Произойдут ли плохие вещи, если я это сделаю? Документы говорят, что это нормально, чтобы перегрузить toString в пространство имен Catch, так что это делает это нормально для operator << перегрузки тоже?

0

Другие решения

Я думаю, что нашел некоторые решения лучше, чем тот, который я дал ранее:


Решение 1:

Обновите Catch до v1.8.2 или новее. Из некоторых быстрых тестов, похоже, v1.8.2 добавлена ​​поддержка std::vector в макросах CAPTURE, без каких-либо дополнительных усилий с вашей стороны. перегрузка operator << за std::vector не требуется в этом случае.


Решение 2:

Если по какой-либо причине вы не можете выполнить обновление до Catch v1.8.2 или новее, это решение аналогично предлагаемому решению в моем первоначальном вопросе, но с улучшениями, основанными на этот ответ от члена комитета C ++ Джонатана Уэйкли (Спасибо!).

Он дает следующий совет:

Не перегружайте операторы для типов, которые вы не контролируете.

Вместо этого создайте крошечный класс адаптера и определите оператор для этого …

Итак, имея в виду:

#include <Catch/single_include/catch.hpp>
#include <vector>
#include <iostream>

template <typename T> struct PrintableVector {
const std::vector<T>& vec_;
};

template <typename T>
PrintableVector<T> makePrintable( const std::vector<T>& vec ) {
return PrintableVector<T>{ vec };
}

template <typename T>
std::ostream& operator << ( std::ostream& os, const PrintableVector<T>& printableVec ) {
for ( const auto& e : printableVec.vec_ ) {
os << e << " ";
}
return os;
}

int some_operation_on_vector( const std::vector<int>& v ) {
return 1;
}

SCENARIO( "some scenario" )
{
GIVEN( "a vector" )
{
const auto the_vector = std::vector<int>{ 1, 2, 3, 4, 5 };

WHEN( "some result is calculated from the vector" )
{
const auto actual_result = some_operation_on_vector( the_vector );

THEN( "the result should be correct.  If not, print out the vector." )
{
const auto expected_result = 0;
CAPTURE( makePrintable( the_vector ) );
REQUIRE( expected_result == actual_result );
}
}
}
}

Это компилирует и запускает на Catch v1.8.1, и дает следующий вывод:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
catchtestexample is a Catch v1.8.1 host application.
Run with -? for options

-------------------------------------------------------------------------------
Scenario: some scenario
Given: a vector
When: some result is calculated from the vector
Then: the result should be correct.  If not, print out the vector.
-------------------------------------------------------------------------------
main.cpp:43
...............................................................................

main.cpp:47: FAILED:
REQUIRE( expected_result == actual_result )
with expansion:
0 == 1
with message:
makePrintable( the_vector ) := 1 2 3 4 5

===============================================================================
test cases: 1 | 1 failed
assertions: 1 | 1 failed
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector