[test] BOOST_CHECK_EQUAL type to stream

I understand why the types of the arguments to BOOST_CHECK_EQUAL (and BOOST_CHECK_PREDICATE, etc.) must have operator<< correctly defined. Otherwise, the failure message could not be properly printed. The type I want to check is vector<int>. But it seems not to be enough to simply define the following function: ostream& operator<<(ostream& out, const vector<int>& vec); The error message is long and very templatey, but the essence is: .../test_tools.hpp:298: error: no match for 'operator<<' in 'ostr << t' What more should I do to be able to use vector<int> in these tests? Thanks! -- Michiel Helvensteijn

AMDG Michiel Helvensteijn wrote:
I understand why the types of the arguments to BOOST_CHECK_EQUAL (and BOOST_CHECK_PREDICATE, etc.) must have operator<< correctly defined. Otherwise, the failure message could not be properly printed. <snip>
What more should I do to be able to use vector<int> in these tests?
Add this at global scope: BOOST_TEST_DONT_PRINT_LOG_VALUE(std::vector<int>); In Christ, Steven Watanabe

Steven Watanabe wrote:
AMDG
Michiel Helvensteijn wrote:
I understand why the types of the arguments to BOOST_CHECK_EQUAL (and BOOST_CHECK_PREDICATE, etc.) must have operator<< correctly defined. Otherwise, the failure message could not be properly printed. <snip>
What more should I do to be able to use vector<int> in these tests?
Add this at global scope: BOOST_TEST_DONT_PRINT_LOG_VALUE(std::vector<int>);
This issue has affected me me as well. Boost.Test doesn't seem to use an instance of std::ostream to print messages..? --John

Steven Watanabe wrote:
What more should I do to be able to use vector<int> in these tests?
Add this at global scope: BOOST_TEST_DONT_PRINT_LOG_VALUE(std::vector<int>);
Yes, that works. But it does defeat the purpose of using BOOST_CHECK_EQUAL and BOOST_CHECK_PREDICATE. Is there a way I can define operator<< so the log value IS printed? Thanks, -- Michiel Helvensteijn

AMDG Michiel Helvensteijn wrote:
Yes, that works. But it does defeat the purpose of using BOOST_CHECK_EQUAL and BOOST_CHECK_PREDICATE. Is there a way I can define operator<< so the log value IS printed?
You have to put it in namespace std. This isn't legal, but it works in practice. In Christ, Steven Watanabe

Steven Watanabe wrote:
AMDG
Michiel Helvensteijn wrote:
Yes, that works. But it does defeat the purpose of using BOOST_CHECK_EQUAL and BOOST_CHECK_PREDICATE. Is there a way I can define operator<< so the log value IS printed?
You have to put it in namespace std. This isn't legal, but it works in practice.
Is it possible & legal to overload the operator for ::boost::wrap_stringstream instead of std::ostream? --John

AMDG John C. Femiani wrote:
Is it possible & legal to overload the operator for ::boost::wrap_stringstream instead of std::ostream?
No good. It gets cast back to an ostream& too soon. A legal (according to the C++ standard at least) way would be to overload for boost::test_tools::tt_detail::print_helper_t<std::vector<T> > instead of vector or to specialize boost::test_tools::tt_detail::print_log_value. In Christ, Steven Watanabe

Steven Watanabe wrote:
A legal (according to the C++ standard at least) way would be to overload for boost::test_tools::tt_detail::print_helper_t<std::vector<T> > instead of vector
Confirmed. I tried this and I kept it. Since given the choice between two working solutions, I'd rather not put anything in namespace std.
or to specialize boost::test_tools::tt_detail::print_log_value.
This I didn't try. It seemed a bit more hack-ish and a bit more work. -- Michiel Helvensteijn

Michiel Helvensteijn wrote:
Steven Watanabe wrote:
or to specialize boost::test_tools::tt_detail::print_log_value.
This I didn't try. It seemed a bit more hack-ish and a bit more work. Well both legal solutions involve using something from a 'detail' namespace, which scares me.
--John

John C. Femiani wrote:
or to specialize boost::test_tools::tt_detail::print_log_value.
This I didn't try. It seemed a bit more hack-ish and a bit more work. Well both legal solutions involve using something from a 'detail' namespace, which scares me.
Hm, yes. You're afraid they will change the structure of that namespace from under our feet without even putting it in a changelog. Given that possibility, might it not be better to put it in namespace std anyway... Perhaps they should offer us a real solution in the next version? -- Michiel Helvensteijn

Michiel Helvensteijn wrote:
John C. Femiani wrote:
or to specialize boost::test_tools::tt_detail::print_log_value.
This I didn't try. It seemed a bit more hack-ish and a bit more work.
Well both legal solutions involve using something from a 'detail' namespace, which scares me.
Hm, yes. You're afraid they will change the structure of that namespace from under our feet without even putting it in a changelog.
Given that possibility, might it not be better to put it in namespace std anyway...
Perhaps they should offer us a real solution in the next version?
Perhaps an overloadable ::boost::repr(T) function that translates T into a proxy type that can have operator<< overloaded properly. e.g. (untested) namespace boost{ template<class T> T const & repr(T const & arg) { return arg; } } namespace boost{ template<class T> std::string repr(std::vector<T> const& arg) { std::ostringstream dst; typename std::vector<T>::iterator i = arg.begin() dst << '{' << repr(*i++); while(i != arg.end()) dst << ',' << repr(*i++); dst << '}'; return dst.str(); } } BTW: I think you can write a ::boost::iterator_range to a stream. (haven't tried from a test macro though). I bet that would be useful for test, program_options, lexical_cast, etc. (If something similar does not already exist). --John

on Thu Jul 17 2008, "John C. Femiani" <john.femiani-AT-gmail.com> wrote:
Michiel Helvensteijn wrote:
John C. Femiani wrote:
or to specialize boost::test_tools::tt_detail::print_log_value.
This I didn't try. It seemed a bit more hack-ish and a bit more work.
Well both legal solutions involve using something from a 'detail' namespace, which scares me.
Hm, yes. You're afraid they will change the structure of that namespace from under our feet without even putting it in a changelog.
Given that possibility, might it not be better to put it in namespace std anyway...
Perhaps they should offer us a real solution in the next version?
Perhaps an overloadable ::boost::repr(T) function that translates T into a proxy type that can have operator<< overloaded properly.
Except that overloading in namespace boost won't work as you'd like in many contexts. You'd need to overload in an associated namespace of T and call repr without qualification. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

David Abrahams wrote:
on Thu Jul 17 2008, "John C. Femiani" <john.femiani-AT-gmail.com> wrote:
Michiel Helvensteijn wrote:
rhaps they should offer us a real solution in the next version?
Perhaps an overloadable ::boost::repr(T) function that translates T into a proxy type that can have operator<< overloaded properly.
Except that overloading in namespace boost won't work as you'd like in many contexts. You'd need to overload in an associated namespace of T and call repr without qualification.
What aspect wouldn't work as I expected? Do you mean that overloads of repr that aren't in namespace boost could occlude ::boost::repr? In that case its a lot like ::boost::begin I think. The point of repr was to avoid putting an overload operator<< into namespace std. --John

AMDG John C. Femiani wrote:
What aspect wouldn't work as I expected? Do you mean that overloads of repr that aren't in namespace boost could occlude ::boost::repr? In that case its a lot like ::boost::begin I think.
You do realize that boost::begin is implemented using range_begin which should be defined in the user's namespace, right? http://www.boost.org/doc/libs/1_35_0/libs/range/doc/boost_range.html#method2
The point of repr was to avoid putting an overload operator<< into namespace std.
The problem: namespace boost { template<class T> void print(const T& t) { std::cout << boost::repr(t); } } namespace boost { void repr(const std::vector<int>&); // Not found by print. } It fails for exactly the same reason that overloading operator<< does. In Christ, Steven Watanabe

Steven Watanabe wrote:
AMDG
John C. Femiani wrote:
What aspect wouldn't work as I expected? Do you mean that overloads of repr that aren't in namespace boost could occlude ::boost::repr? In that case its a lot like ::boost::begin I think.
You do realize that boost::begin is implemented using range_begin which should be defined in the user's namespace, right? http://www.boost.org/doc/libs/1_35_0/libs/range/doc/boost_range.html#method2
Yes, but I thought it worked with std::vector because of the overload of range_begin that is in the boost namespace. A similar strategy would _not_ seem to fix your example though.
It fails for exactly the same reason that overloading operator<< does.
In Christ, Steven
Aaargh., the overload came too late :( Will this approach using template specialization work? //in repr.hpp namespace boost { template<class T> struct repr { typedef T const& type; T const& make(T const& arg){ return arg; } }; template<class T> typename repr<T>::type make_repr(T const& arg){ return ::boost::repr<T>().make(arg); } } //In some code namespace boost { template<class T> void print(const T& t) { std::cout << make_repr(t); } } //This is how you make a proxy namespace boost { template<class T> struct repr<std::vector<T> > { typedef std::string type; std::string make(std::vector<T> const& arg){ return "<vector>"; } }; } --John

Michiel Helvensteijn <m.helvensteijn <at> gmail.com> writes:
Hm, yes. You're afraid they will change the structure of that namespace from under our feet without even putting it in a changelog.
Given that possibility, might it not be better to put it in namespace std anyway...
Perhaps they should offer us a real solution in the next version?
'They' are open to any suggestions ;) Gennadiy

Gennadiy Rozental wrote:
Michiel Helvensteijn <m.helvensteijn <at> gmail.com> writes:
Hm, yes. You're afraid they will change the structure of that namespace from under our feet without even putting it in a changelog.
Given that possibility, might it not be better to put it in namespace std anyway...
Perhaps they should offer us a real solution in the next version?
'They' are open to any suggestions ;)
Gennadiy
I suggested that boost should actually only print adapters to the stream. The default behavior would be to template<class T> struct repr_type{ typedef T type; T make(T value) {return value;} }; template<class T> typename repr_type<T>::type repr(T& value) { return repr_type<T>::make(value); } Then to print log messages: stream << repr<>(obj1) << repr<>(obj2); and to customize output when overloading operator << is not possible, you can use template specialization. template<class T> struct repr_type<std::vector<T> > {...} --John

AMDG John C. Femiani wrote:
Gennadiy Rozental wrote:
'They' are open to any suggestions ;) I suggested that boost should actually only print adapters to the stream. The default behavior would be to
I would prefer to move print_log_value out of tt_detail. In Christ, Steven Watanabe

Steven Watanabe <watanabesj <at> gmail.com> writes:
AMDG
John C. Femiani wrote:
Gennadiy Rozental wrote:
'They' are open to any suggestions ;) I suggested that boost should actually only print adapters to the stream. The default behavior would be to
I would prefer to move print_log_value out of tt_detail.
You mean that this should be the only change or it should be done on top what John suggest?

AMDG Gennadiy Rozental wrote:
Steven Watanabe <watanabesj <at> gmail.com> writes
I would prefer to move print_log_value out of tt_detail.
You mean that this should be the only change or it should be done on top what John suggest?
Yes. I mean that this should be the only change. I don't like to have two interfaces to do exactly the same thing. In Christ, Steven Watanabe

Steven Watanabe wrote:
AMDG
Gennadiy Rozental wrote:
Steven Watanabe <watanabesj <at> gmail.com> writes
I would prefer to move print_log_value out of tt_detail.
You mean that this should be the only change or it should be done on top what John suggest?
Yes. I mean that this should be the only change. I don't like to have two interfaces to do exactly the same thing.
Agreed. I'm sure Steven's approach is better. John

Steven Watanabe <watanabesj <at> gmail.com> writes:
AMDG
Gennadiy Rozental wrote:
Steven Watanabe <watanabesj <at> gmail.com> writes
I would prefer to move print_log_value out of tt_detail.
Done. Gennadiy

Michiel Helvensteijn wrote:
Steven Watanabe wrote:
A legal (according to the C++ standard at least) way would be to overload for boost::test_tools::tt_detail::print_helper_t<std::vector<T> > instead of vector
Confirmed. I tried this and I kept it. Since given the choice between two working solutions, I'd rather not put anything in namespace std.
Ehm. My mistake. The overload worked, but I still had it in namespace std. Without that, it didn't work after all. I'll try your second solution tomorrow. TTGTB *yawn* -- Michiel Helvensteijn

Steven Watanabe wrote:
Yes, that works. But it does defeat the purpose of using BOOST_CHECK_EQUAL and BOOST_CHECK_PREDICATE. Is there a way I can define operator<< so the log value IS printed?
You have to put it in namespace std. This isn't legal, but it works in practice.
Hey, it's only for the test suite. :-) So as far as I'm concerned, it's a great solution. Thanks! -- Michiel Helvensteijn
participants (6)
-
David Abrahams
-
Gennadiy Rozental
-
John C. Femiani
-
John C. Femiani
-
Michiel Helvensteijn
-
Steven Watanabe