[Test] Template specialization problems with BOOST_CHECK_EQUAL_COLLECTIONS
Hi all, I've been using Boost.Test lately and in general it's working well (thanks Gennadiy!). However, I'm having trouble with BOOST_CHECK_EQUAL_COLLECTIONS when my collections are of non-primitive types. For example, if I try: vector<wstring> test1, test2; BOOST_CHECK_EQUAL_COLLECTIONS(test1.begin(), test1.end(), test2.begin(), test2.end()); I get a compiler error along the lines of "h:\libraries\boost\boost\test\utils\wrap_stringstream.hpp(66) : error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const std::basic_string<_Elem,_Traits,_Ax>' (or there is no acceptable conversion)" (with _Elem being wchar_t in this case, and _Traits and _Ax having the usual defaults). Looking at the source I see that BOOST_CHECK_EQUAL_COLLECTIONS is using equal_coll_impl, which is creating a predicate_result and using the stream insertion operator on the wrap_stripstream returned by its message() method. wrap_stringstream has an unspecialized template which delegates to the << operator of the backing ostringstream/ostrstream: template <typename CharT, typename T> inline basic_wrap_stringstream<CharT>& operator<<( basic_wrap_stringstream<CharT>& targ, T const& t ) { targ.stream() << t; return targ; } Since that backing ostringstream descends from ostream, I would have thought that all I needed to do was to ensure that there is a operator << (ostream&, wstring const&) defined, like this: ostream& operator << (ostream& ostr, wstring const& str) { ostr << "I'd put a wstring-to-string function here instead of this constant"; return ostr; } Hower this doesn't work - although I can now compile: ostringstream oss; oss << wstring(L"test"); successfully, if I try: boost::wrap_stringstream wss; wss << wstring(L"test"); or: boost::test_tools::predicate_result res(true); res.message() << wstring(L"test"); I get the same error as above. Interestingly, if I change that << operator implementation so that it takes and returns a wrap_stringstream, instead of an ostream: boost::wrap_stringstream& operator << (boost::wrap_stringstream& ostr, const wstring& str) { ostr << "I'd put a wstring-to-string function here instead of this constant"; return ostr; } then I can compile 'wss << wstring(L"test")' and ' res.message() << wstring(L"test")' OK. This is weird because it suggests to me that that unspecialized wrap_stringstream template that delegates to the ostringstream's << isn't working properly. But weirder is that even having done that, using BOOST_CHECK_EQUAL_COLLECTIONS still produces the same compilation error, even though it's making the same operator call - I can't see why. Am I missing something here? I also tried specializing print_log_value: namespace boost { namespace test_tools { namespace tt_detail { template<> struct print_log_value<std::wstring> { void operator()(std::ostream& ostr, const std::wstring& str) { ostr << "I'd put a wstring-to-string function here instead of this constant"; } }; }}} But that didn't help either - same error. I'm primarily using Visual Studio 2005, but I have exactly the same problems under gcc 3.3.5 too. Any suggestions? Cheers, Will -- Will Bryant http://carcino.gen.nz/ will@core-dev.co.nz +64 21 655 443
Will Bryant wrote:
I get a compiler error along the lines of "h:\libraries\boost\boost\test\utils\wrap_stringstream.hpp(66) : error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const std::basic_string<_Elem,_Traits,_Ax>' (or there is no acceptable conversion)" (with _Elem being wchar_t in this case, and _Traits and _Ax having the usual defaults). ...... template <typename CharT, typename T> inline basic_wrap_stringstream<CharT>& operator<<( basic_wrap_stringstream<CharT>& targ, T const& t ) { targ.stream() << t; return targ; } ........
Since that backing ostringstream descends from ostream, I would have thought that all I needed to do was to ensure that there is a operator << (ostream&, wstring const&) defined, like this:
ostream& operator << (ostream& ostr, wstring const& str) { ostr << "I'd put a wstring-to-string function here instead of this constant"; return ostr; }
I think you need to define this in "namespace std". The targ.stream() << t; code is inside operator<< in namespace boost. That operator hides all global operators<< you might have. The only way your operator for wstring can be found is via ADL, so you need to put it in namespace std. - Volodya
Vladimir Prus wrote:
think you need to define this in "namespace std". The
targ.stream() << t;
code is inside operator<< in namespace boost. That operator hides all global operators<< you might have. The only way your operator for wstring can be found is via ADL, so you need to put it in namespace std.
Thanks, that solved it. Cheers, Will -- Will Bryant http://carcino.gen.nz/ will@core-dev.co.nz +64 21 655 443
participants (2)
-
Vladimir Prus
-
Will Bryant