The attached file contains my attempt to update lib.alg.transform tests and port it to new test driver.
With best wishes, Anton Pevtsov
/*************************************************************************** * * transform.cpp - test exercising 25.2.3 [lib.alg.transform] * * $Id: //stdlib/dev/tests/stdlib/algorithm/transform.cpp#18 $ * *************************************************************************** * * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave * Software division. Licensed under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0. Unless required by * applicable law or agreed to in writing, software distributed under * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License * for the specific language governing permissions and limitations under * the License. * **************************************************************************/ #include <algorithm> // for transform #include <cstddef> // for size_t #include <alg_test.h> #include <driver.h> // for rw_test() _RWSTD_NAMESPACE (std) { // disable explicit instantiation for compilers (like MSVC) // that can't handle it #ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION template OutputIter<assign<base<> > > transform (InputIter<assign<base<> > >, InputIter<assign<base<> > >, OutputIter<assign<base<> > >, func<assign<base<> > >); template OutputIter<assign<base<> > > transform (InputIter<assign<base<> > >, InputIter<assign<base<> > >, InputIter<assign<base<> > >, OutputIter<assign<base<> > >, binary_func<assign<base<> > >); #endif // _RWSTD_NO_EXPLICIT_INSTANTIATION } // namespace std /**************************************************************************/ template <class T> struct incT { incT (int dummy) { funcalls_ = 0; dummy_ = dummy; } T operator() (const T &x) const { ++funcalls_; T y(x); y.val_ += 1; return y; } // dummy operator T operator() (const T &a, const T &b) const { _RWSTD_UNUSED(b); return a; } int dummy_; static std::size_t funcalls_; }; template <class T> struct plusT { plusT (int dummy) { funcalls_ = 0; dummy_ = dummy; } // dummy operator T operator() (const T &a) const { return a; } T operator() (const T &a, const T &b) const { ++funcalls_; T x(a); x.val_ = a.val_ + b.val_; return x; } int dummy_; static std::size_t funcalls_; }; template <class T> std::size_t incT<T>::funcalls_; template <class T> std::size_t plusT<T>::funcalls_; /**************************************************************************/ template <class T, class InputIterator1, class InputIterator2, class OutputIterator, class Function> void test_transform (const std::size_t line, const std::size_t N, const InputIterator1& it1, const InputIterator2& it2, const OutputIterator& out, const Function& fun_dummy, const T* , int same_seq, bool binary) { static const char* const it1name = type_name (it1, (T*)0); static const char* const it2name = type_name (it2, (T*)0); static const char* const outname = type_name (out, (T*)0); static const char* const fname = "transform"; static const char* const funname = binary ? "binary_function" : "unary_function"; _RWSTD_UNUSED(fun_dummy); rw_info (0, 0, 0, "std::%s (%s, %2$s%{?}, %s%{;}, %s, %s)%{?}, %s%d == %s%{;}", fname, it1name, binary, it2name, outname, funname, same_seq, "first", same_seq, "dest"); // generate sequential values for each default constructed T T::gen_ = gen_seq; // use ::operator new() to prevent default initialization T *buf1 = new T [N]; T* buf2 = new T [N]; T* buf3 = same_seq ? (same_seq == 1 ? buf1 : buf2) : new T [N]; int start1_val = same_seq == 2 ? buf2[0].val_ : buf1[0].val_; int start2_val = same_seq == 2 ? buf1[0].val_ : buf2[0].val_; for (std::size_t i = 0; i < N; ++i) { const InputIterator1 first1 = make_iter (buf1, buf1, buf1 + i + 1, it1); const InputIterator1 last = make_iter (buf1 + i + 1, buf1, buf1 + i + 1, it1); const InputIterator2 first2 = make_iter (buf2, buf2, buf2 + i + 1, it2); const OutputIterator dest = make_iter (buf3, buf3, buf3 + i + 1, out); Function fun(0); // exercise 25.2.3 - std::transform<> () const OutputIterator result = binary ? std::transform (first1, last, first2, dest, fun) : std::transform (first1, last, dest, fun); // check the returned iterator bool success = result.cur_ == buf3 + i + 1; rw_assert (success, 0, line, "std::%s (%s, %2$s%{?}, %s%{;}, %s, %s)%{?}, " "%s%d == %s%{;} : return val: " "dest + %td, expected dest + %zu at step %zu", fname, it1name, binary, it2name, outname, funname, same_seq, "first", same_seq, "dest", result.cur_ - buf3, i + 1, i + 1); if (!success) break; // check the transformation results int exp_val = 0; std::size_t j = 0; for ( ; j < i + 1; j++) { if (0 == same_seq) { exp_val = binary ? start1_val + int(j) + start2_val + int(j) : start1_val + int(j) + 1; } else { exp_val = binary ? start1_val + int(j) + (start2_val + int(j)) * int(i + 1 - j) : start1_val + int(i + 1); } success = (buf3 + j)->val_ == exp_val; if (! success) break; } rw_assert (success, 0, line, "std::%s (%s, %2$s%{?}, %s%{;}, %s, %s)%{?}, " "%s%d == %s%{;} : error: incorrect value %d, " "expected %d, position %zu, step %zu", fname, it1name, binary, it2name, outname, funname, same_seq, "first", same_seq, "dest", (buf3 + j)->val_, exp_val, j + 1, i + 1); if (!success) break; // check compexity, 25.2.3 p4 rw_assert (Function::funcalls_ == i + 1, 0, line, "std::%s (%s, %2$s%{?}, %s%{;}, %s, %s)%{?}, " "%s%d == %s%{;} : complexity : %zu " "applications of %5$s, expected %zu", fname, it1name, binary, it2name, outname, funname, same_seq, "first", same_seq, "dest", Function::funcalls_, i + 1); } delete[] buf1; delete[] buf2; if (0 == same_seq) delete[] buf3; } /**************************************************************************/ /* extern */ int rw_opt_nloops = 32; // --nloops=# /* extern */ int rw_opt_no_unary_function; // --no-unary_function /* extern */ int rw_opt_no_binary_function; // --no-binary_function /* extern */ int rw_opt_no_input_iter; // --no-InputIterator /* extern */ int rw_opt_no_output_iter; // --no-OutputIterator /* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator /* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator /* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator template <class T, class InputIterator1, class InputIterator2, class OutputIterator, class Function> void test_transform (const std::size_t N, const T* , const InputIterator1& it1, const InputIterator2& it2, const OutputIterator& out, const Function& fun_dummy, int tag1, int tag2, int tag3, int same_seq, bool binary) { // tag1, tag2 and tag3 determines the necessity of the iterator generation // on the corresponding position and other positions there the iterator // will be used // for all tags: // 0 means that no iterator is needed here // (maybe it was already generated or just not needed) // 1 means that the iterator is needed on this position // (first for tag1, second for tag2, etc) // 2 means that the iterator is needed on this position and the // same type of iterator should be used at third position if (rw_opt_no_input_iter) { if (1 == tag1 || 0 == tag1 && 1 == tag2) rw_note (0, __FILE__, __LINE__, "InputIterator test disabled"); } else { if (1 == tag1) { test_transform (N, (T*) 0, InputIter<T>((T*)0, (T*)0, (T*)0), it2, out, fun_dummy, 0, tag2, tag3, same_seq, binary); } else if (0 == tag1 && 1 == tag2) { test_transform (N, (T*) 0, it1, InputIter<T>((T*)0, (T*)0, (T*)0), out, fun_dummy, tag1, 0, tag3, same_seq, binary); } } if (rw_opt_no_fwd_iter) { if (tag1 || !tag1 && tag2 || !tag1 && !tag2 && tag3) rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled"); } else { if (1 == tag1) { test_transform (N, (T*) 0, FwdIter<T>(), it2, out, fun_dummy, 0, tag2, tag3, same_seq, binary); } else if (2 == tag1) { test_transform (N, (T*) 0, FwdIter<T>(), it2, FwdIter<T>(), fun_dummy, 0, tag2, 0, same_seq, binary); } else if (0 == tag1 && 1 == tag2) { test_transform (N, (T*) 0, it1, FwdIter<T>(), out, fun_dummy, tag1, 0, tag3, same_seq, binary); } else if (0 == tag1 && 2 == tag2) { test_transform (N, (T*) 0, it1, FwdIter<T>(), FwdIter<T>(), fun_dummy, tag1, 0, 0, same_seq, binary); } else if (0 == tag1 && 0 == tag2 && 1 == tag3) { test_transform (N, (T*) 0, it1, it2, FwdIter<T>(), fun_dummy, tag1, tag2, 0, same_seq, binary); } } if (rw_opt_no_bidir_iter) { if (tag1 || !tag1 && tag2 || !tag1 && !tag2 && tag3) rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled"); } else { if (1 == tag1) { test_transform (N, (T*) 0, BidirIter<T>(), it2, out, fun_dummy, 0, tag2, tag3, same_seq, binary); } else if (2 == tag1) { test_transform (N, (T*) 0, BidirIter<T>(), it2, BidirIter<T>(), fun_dummy, 0, tag2, 0, same_seq, binary); } else if (0 == tag1 && 1 == tag2) { test_transform (N, (T*) 0, it1, BidirIter<T>(), out, fun_dummy, tag1, 0, tag3, same_seq, binary); } else if (0 == tag1 && 2 == tag2) { test_transform (N, (T*) 0, it1, BidirIter<T>(), BidirIter<T>(), fun_dummy, tag1, 0, 0, same_seq, binary); } else if (0 == tag1 && 0 == tag2 && 1 == tag3) { test_transform (N, (T*) 0, it1, it2, BidirIter<T>(), fun_dummy, tag1, tag2, 0, same_seq, binary); } } if (rw_opt_no_rnd_iter) { if (tag1 || !tag1 && tag2 || !tag1 && !tag2 && tag3) rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled"); } else { if (1 == tag1) { test_transform (N, (T*) 0, RandomAccessIter<T>(), it2, out, fun_dummy, 0, tag2, tag3, same_seq, binary); } else if (2 == tag1) { test_transform (N, (T*) 0, RandomAccessIter<T>(), it2, RandomAccessIter<T>(), fun_dummy, 0, tag2, 0, same_seq, binary); } else if (0 == tag1 && 1 == tag2) { test_transform (N, (T*) 0, it1, RandomAccessIter<T>(), out, fun_dummy, tag1, 0, tag3, same_seq, binary); } else if (0 == tag1 && 2 == tag2) { test_transform (N, (T*) 0, it1, RandomAccessIter<T>(), RandomAccessIter<T>(), fun_dummy, tag1, 0, 0, same_seq, binary); } else if (0 == tag1 && 0 == tag2 && 1 == tag3) { test_transform (N, (T*) 0, it1, it2, RandomAccessIter<T>(), fun_dummy, tag1, tag2, 0, same_seq, binary); } } if (rw_opt_no_output_iter) { if (0 == tag1 && 0 == tag2 && 1 == tag3) rw_note (0, __FILE__, __LINE__, "OutputIterator test disabled"); } else { if (0 == tag1 && 0 == tag2 && 1 == tag3) { test_transform (N, (T*) 0, it1, it2, OutputIter<T>((T*)0, (T*)0, (T*)0), fun_dummy, tag1, tag2, 0, same_seq, binary); } } if (0 == tag1 && 0 == tag2 && 0 == tag3) { test_transform (__LINE__, N, it1, it2, out, fun_dummy, (T*)0, same_seq, binary); } } static int run_test (int, char*[]) { const std::size_t N = std::size_t (rw_opt_nloops); // test transform with an unary function // according to 25.2.3 p5 'result may be equal to first' // so it is neccessary to test this case separately if (rw_opt_no_unary_function) { rw_note (0, __FILE__, __LINE__, "std::transform unary function test disabled"); } else { test_transform (N, (X*) 0, InputIter<X>((X*)0, (X*)0, (X*)0), RandomAccessIter<X>(), RandomAccessIter<X>(), incT<X>(0), 1, 0, 1, 0, false); // test 25.2.3 p5 - result is equal to first // so set tag1 = 2 and tag3 = 0 to test all iterators at // first position and avoid iterators generation at third pos // set same_seq to 1 to indicate that first and dest should be // the same iterators test_transform (N, (X*) 0, InputIter<X>((X*)0, (X*)0, (X*)0), RandomAccessIter<X>(), RandomAccessIter<X>(), incT<X>(0), 2, 0, 0, 1, false); } // test transform with a binary function // according to 25.2.3 p5 'result may be equal to first1 or first2' // so it is neccessary to test these cases separately if (rw_opt_no_binary_function) { rw_note (0, __FILE__, __LINE__, "std::transform binary function test disabled"); } else { test_transform (N, (X*) 0, InputIter<X>((X*)0, (X*)0, (X*)0), RandomAccessIter<X>(), RandomAccessIter<X>(), plusT<X>(0), 1, 1, 1, 0, true); // test 25.2.3 p5 - result is equal to first2 // so set tag2 = 2 and tag3 = 0 to test all iterators at // second position and avoid iterators generation at third pos // set same_seq to 2 to indicate that first2 and dest should be // the same iterators test_transform (N, (X*) 0, InputIter<X>((X*)0, (X*)0, (X*)0), RandomAccessIter<X>(), RandomAccessIter<X>(), plusT<X>(0), 1, 2, 0, 2, true); // test 25.2.3 p5 - result is equal to first1 // so set tag1 = 2 and tag3 = 0 to test all iterators at // first position and avoid iterators generation at third pos // set same_seq to 1 to indicate that first1 and dest should be // the same iterators test_transform (N, (X*) 0, InputIter<X>((X*)0, (X*)0, (X*)0), RandomAccessIter<X>(), RandomAccessIter<X>(), plusT<X>(0), 2, 1, 0, 1, true); } return 0; } /**************************************************************************/ int main (int argc, char *argv[]) { return rw_test (argc, argv, __FILE__, "lib.alg.transform", 0 /* no comment */, run_test, "|-nloops#0 " // must be non-negative "|-no-unary_function# " "|-no-binary_function# " "|-no-InputIterator# " "|-no-OutputIterator# " "|-no-ForwardIterator# " "|-no-BidirectionalIterator# " "|-no-RandomAccessIterator", &rw_opt_nloops, &rw_opt_no_unary_function, &rw_opt_no_binary_function, &rw_opt_no_input_iter, &rw_opt_no_output_iter, &rw_opt_no_fwd_iter, &rw_opt_no_bidir_iter, &rw_opt_no_rnd_iter); }
