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);
}

Reply via email to