在Boost.Test中使用BOOST_CHECK_EQUAL_COLLECTION打印std :: tuple的std :: vector

时间:2016-02-26 13:38:34

标签: c++11 boost boost-test

您好我正在尝试使用Boost.Test进行单元测试。但是我的一些函数返回std::vector< std::tuple< TypeA, TypeB > >中的元组集合。

要使用BOOST_CHECK_EQUALSBOOST_CHECK_EQUAL_COLLECTION,我专门boost::test_tools::print_log_value打印好的元组和向量,the answer to this question解释。我还为元组提供operator<<,以便我的向量可以在打印整个向量时使用它。为了清洁,这个操作符位于空白名称空间中。

但编译失败,因为boost::test_tools::print_log_value <std::vector<std::tuple<...>>>的实现无法找到元组的operator<<

这是一个最小的代码,对不起,已经非常详细了。

#define BOOST_TEST_MODULE my_test
#include <boost/test/included/unit_test.hpp>

#include <tuple>
#include <vector>

/////////////////
// std::vector //
/////////////////

// boost printing method
namespace boost {
namespace test_tools {
template< typename Type >
struct print_log_value< std::vector< Type > > {
    void operator()( std::ostream& s, const std::vector< Type > &collection ) {
        const int size = collection.size();

        if( size == 0 ) {
            s << "[]";
        }
        else {
            s << "[ ";
            for( int i =0; i <= size-2; ++i ) {
                s << collection[i] << ", ";
            }
            s << collection[size-1] << " ]";
        }
        return s;
    }
};
} //namespace test_tools
} //namespace boost

////////////////
// std::tuple //
////////////////

// recursive calls for printing
namespace tuple_print_aux{

    template< int I, int J, typename... Types >
    struct recursive_printer {
        static void print( std::ostream& s, const std::tuple<Types...> &collection ) {
            s << std::get< I >( collection ) << ", ";
            recursive_printer< I+1, J-1, Types... >::print( s, collection );
        }
    };

    template< int I, typename... Types >
    struct recursive_printer< I, 1, Types... > {
        static void print( std::ostream& s, const std::tuple<Types...> &collection ) {
            s << std::get< I >( collection );
        }
    };

    template< typename... Types >
    void recursive_print( std::ostream& s, const std::tuple<Types...> &collection ) {
        recursive_printer< 0, sizeof...(Types), Types... >::print( s, collection );
    }
}

// output stream operator
template< typename... Types >
std::ostream& operator<<( std::ostream& s, const std::tuple<Types...> &collection ) {
    s << "( ";
    tuple_print_aux::recursive_print< Types... >( s, collection );
    s << " )";
    return s;
}

// boost printing method
namespace boost {
namespace test_tools {
template< typename... Types >
struct print_log_value< std::tuple< Types... > > {
    void operator()( std::ostream& s, const std::tuple<Types...> &collection ) {
        s << "( ";
        tuple_print_aux::recursive_print< Types... >( s, collection );
        s << " )";
    }
};
} //namespace test_tools
} //namespace boost

BOOST_AUTO_TEST_CASE(my_test_case) {
    //builds successfully
    BOOST_CHECK_EQUAL( std::make_tuple(1,"a"), std::make_tuple(1,"a") );

    //builds successfully
    std::vector< int > v( 2, 3 ), w( 2, 7 );
    BOOST_CHECK_EQUAL_COLLECTIONS( v.begin(), v.end(), w.begin(), w.end() );

    //fails to build
    std::vector< std::tuple<int,int> > a( 1, std::make_tuple(1,3) ), b( 1, std::make_tuple(2,2) );
    BOOST_CHECK_EQUAL_COLLECTIONS( a.begin(), a.end(), b.begin(), b.end() );
};

当然,将operator<< std::tuple放入std命名空间可以解决问题,但这是一个非标准的非优雅解决方案。 那么......我该如何处理这个问题呢。 ?

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我相信你应该宣布

template< typename... Types >
std::ostream& operator<<( std::ostream& s, const std::tuple<Types...> &collection )
struct print_log_value< std::vector< Type > >之前

。另外我认为struct print_log_value元组的专业化就足够了,因为BOOST_CHECK_EQUAL_COLLECTIONS实际上看不到std::vector,而是它上面的迭代器。