2

Catch Unit Test v1.8.1 では、gcc 6.2.0 を使用して、ベクトルをINFO(...)orに渡すことで、テストが失敗したときにベクトルの内容を便利に出力しようとしてい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()マクロに渡すためにコードがコンパイルされません。

Catch docs に従って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()を受け入れる唯一の方法は、オーバーロードを不正に namespaceに入れることです。std::vectoroperator<<std

これを行うための適切で合法的な方法はありますか?

4

2 に答える 2