
On 12/10/05 10:55 PM, "Andrew n marshall" <amarshal@ISI.EDU> wrote:
I've encountered a problem when transitioning from Boost.Test 1.32 to 1.33. New to 1.33 is a set_precision(..) method on the print_log_value functor (in test_tools.hpp). The problem, as I see it, is the use of numeric_limits<T>, which exposes the assumption T is a numeric entity at all. I'm actually surprised it compiles as often as it does, so maybe my blame is misdirected. Nonetheless, I was able to create the attached test case to prove my point. I've also included the generated build log with the really nasty compile time error. [TRUNCATE Mr. Marshall's code example]
Your blame may be misdirected. Looking at the Boost.Test code: template<typename T> struct print_log_value { void operator()( std::ostream& ostr, T const& t ) { typedef typename mpl::or_<is_array<T>,is_function<T> >::type couldnt_use_nl; set_precision( ostr, couldnt_use_nl() ); ostr << t; // by default print the value } void set_precision( std::ostream& ostr, mpl::false_ ) { if( std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::radix == 2 ) ostr.precision( 2 + std::numeric_limits<T>::digits * 301/1000 ); } void set_precision( std::ostream&, mpl::true_ ) {} }; it uses std::numeric_limits<>::is_specialized to make sure that the precision is set only for numeric types. Otherwise, that function does nothing. The functor's operator() splits the code according to type, and types that don't even make it to the set_precision you're talking about also do nothing. Actually, since the is_specialized field should be a compile-time constant, the code should be shifted to compile-time even further: template<typename T> struct print_log_value { void operator()( std::ostream& ostr, T const& t ) { typedef typename mpl::or_<is_array<T>,is_function<T>, mpl::bool_<!std::numeric_limits<T>::is_specialized> >::type couldnt_use_nl; set_precision( ostr, couldnt_use_nl() ); ostr << t; // by default print the value } void set_precision( std::ostream& ostr, mpl::false_ ) { ostr.precision( 2 + std::numeric_limits<T>::digits * 301/1000 ); } void set_precision( std::ostream&, mpl::true_ ) {} }; Of course, this code assumes that std::numeric_limits<>::radix is 2. The 301/1000 is a logarithm conversion factor to turn a power of 2 into a power of 10, with two extra digits for slop. This lets us print out a number to all of its defined digits in decimal. Maybe more compile-time conditions should be added to confirm those assumptions. Any type that doesn't pass the test is assumed to be non-numeric and hopefully will print out enough of its state to be unambiguous without setting the precision. As far as your code is concerned, I think it should work. You always should be able to convert pointers/references to a base class, even if it's abstract. And you should be able to work/channel through those pointers and references. The only thing pure-virtual member functions block is creating an object directly of the abstract type. But I don't see any slice & copy action here. -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com