tr1/test_function_tricky trickier than needed

The only reason for test_function_tricky.cpp to not compile with boost::function is the presence of the following two lines: BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::unary_function<int, long>, std::tr1::function<long (int)> >::value)); BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::binary_function<int, char, double>, std::tr1::function<double (int,char)> >::value)); that check for the (highly questionable and not particularly relevant) requrement that function<> should derive from unary_function or binary_function in some cases. I think that these two lines need to be moved to a separate test.

Peter Dimov wrote:
The only reason for test_function_tricky.cpp to not compile with boost::function is the presence of the following two lines:
BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::unary_function<int, long>, std::tr1::function<long (int)> >::value));
BOOST_STATIC_ASSERT((::boost::is_base_and_derived<std::binary_function<int, char, double>, std::tr1::function<double (int,char)> >::value));
that check for the (highly questionable and not particularly relevant) requrement that function<> should derive from unary_function or binary_function in some cases.
Questionable maybe, but none the less part of the TR1.
I think that these two lines need to be moved to a separate test.
The only difference between this test and the "non-tricky" one is the presence of those two lines. The test is intentionally pedantic. John.

John Maddock wrote:
I think that these two lines need to be moved to a separate test.
The only difference between this test and the "non-tricky" one is the presence of those two lines. The test is intentionally pedantic.
It didn't occur to me to look at the non-tricky test. :-) Why did you decide to duplicate all non-tricky portions in the tricky test as well? We are running both.

Peter Dimov wrote:
The only difference between this test and the "non-tricky" one is the presence of those two lines. The test is intentionally pedantic.
It didn't occur to me to look at the non-tricky test. :-)
Why did you decide to duplicate all non-tricky portions in the tricky test as well? We are running both.
Well originally they weren't supposed to be tricky: there was supposed to be one test that "concept checked" each TR1 section, when I found that Boost didn't support a few of the features, I just commented out those parts that Boost didn't support and made these the "non-tricky" tests, and the "complete" unmolested versions became the "tricky" tests. John.

John Maddock wrote:
Peter Dimov wrote:
The only difference between this test and the "non-tricky" one is the presence of those two lines. The test is intentionally pedantic.
It didn't occur to me to look at the non-tricky test. :-)
Why did you decide to duplicate all non-tricky portions in the tricky test as well? We are running both.
Well originally they weren't supposed to be tricky: there was supposed to be one test that "concept checked" each TR1 section, when I found that Boost didn't support a few of the features, I just commented out those parts that Boost didn't support and made these the "non-tricky" tests, and the "complete" unmolested versions became the "tricky" tests.
Ah, I see. Thanks for the explanation. This means that my patch to test_bind_tricky has been completely misguided, sorry about that. Feel free to revert it. However, this situation is problematic for several reasons. * There is code duplication among the tricky and non-tricky tests, and this creates a possibility for them to diverge without us noticing. * Someone like me that doesn't pay the necessary attention can inadvertently "fix" something that doesn't need fixing. * The current separation of tricky == "100% TR1 compliant", non-tricky == "happens to work today" doesn't help us track incremental improvements in conformance. For example, consider the hypothetical situation in which someone makes changes to bind that are supposed to make these tests: //BOOST_STATIC_ASSERT(::std::tr1::is_placeholder<T>::value); //BOOST_STATIC_ASSERT(::std::tr1::is_bind_expression<Binder>::value); pass. This won't be reflected in the test matrix as the non-tricky test has them commented and the tricky test will still fail for several other reasons. (As an aside, your tricky bind test doesn't test user specializations of is_placeholder and is_bind_expression.) * We need to have a clear idea what is the purpose of the strict conformance ("tricky") tests. Do we keep them since we expect that these tests will one day pass under the boost implementation? Or do we implicitly acknowledge the fact that they will never pass, and just keep running them out of principle? To take bind as an example, I don't expect it ever passing the "placeholder as const T&" test because of the header-only nature of the implementation and real-world precompiled header limitations. So why keep testing that? We know that it will fail. (Note that this is a non-rhetorical question. There might be a reason, we/I just need to know what it is.) Finally, we might want to try inserting the following lines: #if BOOST_FUNCTION_NUM_ARGS == 1 , public std::unary_function<T0,R> #elif BOOST_FUNCTION_NUM_ARGS == 2 , public std::binary_function<T0,T1,R> #endif in function_template.hpp:449; this will hopefully allow us to dispense with one of the tricky tests. :-)

Peter Dimov wrote:
However, this situation is problematic for several reasons.
* There is code duplication among the tricky and non-tricky tests, and this creates a possibility for them to diverge without us noticing.
Yep.
* Someone like me that doesn't pay the necessary attention can inadvertently "fix" something that doesn't need fixing.
:-)
* The current separation of tricky == "100% TR1 compliant", non-tricky == "happens to work today" doesn't help us track incremental improvements in conformance. For example, consider the hypothetical situation in which someone makes changes to bind that are supposed to make these tests:
//BOOST_STATIC_ASSERT(::std::tr1::is_placeholder<T>::value);
//BOOST_STATIC_ASSERT(::std::tr1::is_bind_expression<Binder>::value);
pass. This won't be reflected in the test matrix as the non-tricky test has them commented and the tricky test will still fail for several other reasons.
Understood, we need to decide just how many tests to split this up into I guess.
(As an aside, your tricky bind test doesn't test user specializations of is_placeholder and is_bind_expression.)
* We need to have a clear idea what is the purpose of the strict conformance ("tricky") tests. Do we keep them since we expect that these tests will one day pass under the boost implementation? Or do we implicitly acknowledge the fact that they will never pass, and just keep running them out of principle?
To take bind as an example, I don't expect it ever passing the "placeholder as const T&" test because of the header-only nature of the implementation and real-world precompiled header limitations. So why keep testing that? We know that it will fail. (Note that this is a non-rhetorical question. There might be a reason, we/I just need to know what it is.)
Don't forget that Boost.TR1 need not be actually using Boost: if there is a version of TR1 supplied with the std lib in use then Boost.TR1 can use that (actually it *has* to use it if TR1 is in the include path). In this case these tests may well pass: for example quite a few of them do if you enable support for the fledgling TR1 implementation in gcc-4.0.x. Last time I looked the gcc TR1 implementation wasn't quite ready to be used as the default (so the tests still fail) but I do expect it to become the default at some point, at which time the tests should all go green for that compiler.
Finally, we might want to try inserting the following lines:
#if BOOST_FUNCTION_NUM_ARGS == 1
, public std::unary_function<T0,R>
#elif BOOST_FUNCTION_NUM_ARGS == 2
, public std::binary_function<T0,T1,R>
#endif
in function_template.hpp:449; this will hopefully allow us to dispense with one of the tricky tests. :-)
That would be cool. Recent fixes to Boost.Array means we can dispense with that one as well I believe. John.

John Maddock wrote:
Peter Dimov wrote:
* Someone like me that doesn't pay the necessary attention can inadvertently "fix" something that doesn't need fixing.
:-)
Well, for what it's worth, test_bind_tricky _is_ passing for g++ 4.1.1 now. :-) And so is test_function_tricky, for different reasons. However, test_boost seems to have started failing, presumably because I added an #include <functional> to boost/function.hpp to bring in unary_function and binary_function and this probably created a header loop. Any ideas on how we might fix that?

Peter Dimov wrote:
John Maddock wrote:
Peter Dimov wrote:
* Someone like me that doesn't pay the necessary attention can inadvertently "fix" something that doesn't need fixing.
:-)
Well, for what it's worth, test_bind_tricky _is_ passing for g++ 4.1.1 now. :-) And so is test_function_tricky, for different reasons. However, test_boost seems to have started failing, presumably because I added an #include <functional> to boost/function.hpp to bring in unary_function and binary_function and this probably created a header loop. Any ideas on how we might fix that?
Try using <boost/config/no_tr1/functional.hpp> rather than <functional> (the former suppresses inclusion of the TR1 <functional> code even if Boost.TR1 is in the path). John.
participants (2)
-
John Maddock
-
Peter Dimov