예제 #1
0
파일: deque.cpp 프로젝트: Quna/mspdev
void deal_cards (It, It2 end)
{
    for (int i = 0; i < 5; i++) {
        current_hand.insert (current_hand.begin (), *end);
        deck_of_cards.erase (end++);
    }
}
예제 #2
0
void exception_loop (int              line /* line number in caller*/,
                     MemberFunction   mfun /* deque member function */,
                     const char      *fcall /* function call string */,
                     int              exceptions /* enabled exceptions */,
                     Deque           &deq /* container to call function on */,
                     const Deque::iterator &it /* iterator into container */,
                     int              n /* number of elements or offset */,
                     const UserClass *x /* pointer to an element or 0 */,
                     const Iterator  &first /* beginning of range */,
                     const Iterator  &last /* end of range to insert */,
                     int             *n_copy /* number of copy ctors */,
                     int             *n_asgn /* number of assignments */)
{
    std::size_t throw_after = 0;

    // get the initial size of the container and its begin() iterator
    // to detect illegal changes after an exception (i.e., violations
    // if the strong exception guarantee)
    const std::size_t           size  = deq.size ();
    const Deque::const_iterator begin = deq.begin ();
    const Deque::const_iterator end   = deq.end ();

#ifdef DEFINE_REPLACEMENT_NEW_AND_DELETE

    rwt_free_store* const pst = rwt_get_free_store (0);

#endif   // DEFINE_REPLACEMENT_NEW_AND_DELETE

    // repeatedly call the specified member function until it returns
    // without throwing an exception
    for ( ; ; ) {

        // detect objects constructed but not destroyed after an exception
        std::size_t x_count = UserClass::count_;

        _RWSTD_ASSERT (n_copy);
        _RWSTD_ASSERT (n_asgn);

        *n_copy = UserClass::n_total_copy_ctor_;
        *n_asgn = UserClass::n_total_op_assign_;

#ifndef _RWSTD_NO_EXCEPTIONS

        // iterate for `n=throw_after' starting at the next call to operator
        // new, forcing each call to throw an exception, until the insertion
        // finally succeeds (i.e, no exception is thrown)

#  ifdef DEFINE_REPLACEMENT_NEW_AND_DELETE

        if (exceptions & NewThrows) {
            *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_after + 1;
        }

#  endif   // DEFINE_REPLACEMENT_NEW_AND_DELETE

        if (exceptions & CopyCtorThrows) {
            UserClass::copy_ctor_throw_count_ =
                UserClass::n_total_copy_ctor_ + throw_after;
        }

        if (exceptions & AssignmentThrows) {
            UserClass::op_assign_throw_count_ =
                UserClass::n_total_op_assign_ + throw_after;
        }

#endif   // _RWSTD_NO_EXCEPTIONS

        _TRY {

            switch (mfun) {
            case Assign_n:
                _RWSTD_ASSERT (x);
                deq.assign (n, *x);
                break;
            case AssignRange:
                deq.assign (first, last);
                break;

            case Erase_1:
                deq.erase (it);
                break;
            case EraseRange: {
                const Deque::iterator erase_end (it + n);
                deq.erase (it, erase_end);
                break;
            }

            case Insert_1:
                _RWSTD_ASSERT (x);
                deq.insert (it, *x);
                break;
            case Insert_n:
                _RWSTD_ASSERT (x);
                deq.insert (it, n, *x);
                break;
            case InsertRange:
                deq.insert (it, first, last);
                break;
            }
        }
        _CATCH (...) {

            // verify that an exception thrown from the member function
            // didn't cause a change in the state of the container

            rw_assert (deq.size () == size, 0, line,
                       "line %d: %s: size unexpectedly changed "
                       "from %zu to %zu after an exception",
                       __LINE__, fcall, size, deq.size ());
            
            rw_assert (deq.begin () == begin, 0, line,
                       "line %d: %s: begin() unexpectedly "
                       "changed after an exception by %td",
                       __LINE__, fcall, deq.begin () - begin);

            rw_assert (deq.end () == end, 0, line,
                       "line %d: %s: end() unexpectedly "
                       "changed after an exception by %td",
                       __LINE__, fcall, deq.end () - end);
            

            // count the number of objects to detect leaks
            x_count = UserClass::count_ - x_count;
            rw_assert (x_count == deq.size () - size, 0, line,
                       "line %d: %s: leaked %zu objects after an exception",
                       __LINE__, fcall, x_count - (deq.size () - size));
            
            if (exceptions) {

                // increment to allow this call to operator new to succeed
                // and force the next one to fail, and try to insert again
                ++throw_after;
            }
            else
                break;

            continue;
        }

        // count the number of objects to detect leaks
        x_count = UserClass::count_ - x_count;
        rw_assert (x_count == deq.size () - size, 0, line,
                   "line %d: %s: leaked %zu objects "
                   "after a successful insertion",
                   __LINE__, fcall, x_count - (deq.size () - size));

        break;
    }