why a member "swap" function shouldn't throw?

Discussion in 'C++' started by Jess, Jun 15, 2007.

  1. Jess

    Jess Guest

    Hello,

    It is said that if I implement a "swap" member function, then it
    should never throw any exception. However, if I implement "swap" non-
    member function, then the restriction doesn't apply. Can somebody tell
    me why?

    Thanks,
    Jess
     
    Jess, Jun 15, 2007
    #1
    1. Advertising

  2. Jess

    Daniel T. Guest

    Jess <> wrote:

    > It is said that if I implement a "swap" member function, then it
    > should never throw any exception. However, if I implement "swap" non-
    > member function, then the restriction doesn't apply. Can somebody tell
    > me why?


    I think the restriction should apply with non-member functions as well.
     
    Daniel T., Jun 15, 2007
    #2
    1. Advertising

  3. Jess

    dasjotre Guest

    On 15 Jun, 13:21, Jess <> wrote:
    > Hello,
    >
    > It is said that if I implement a "swap" member function, then it
    > should never throw any exception. However, if I implement "swap" non-
    > member function, then the restriction doesn't apply. Can somebody tell
    > me why?
    >


    I think that the restriction must apply regardless to whether it is
    member or not.

    consider

    struct A
    {
    T1 t1_;
    T2 t2_;
    };

    void swap(A & l, A & r)
    {
    swap(l.t1, r.t1);
    swap(l.t2, r.t2);
    }

    and second swap throws, then you have
    half swapped objects.

    regards

    DS
     
    dasjotre, Jun 15, 2007
    #3
  4. dasjotre wrote:

    > void swap(A & l, A & r)
    > {
    > swap(l.t1, r.t1);
    > swap(l.t2, r.t2);
    > }
    >
    > and second swap throws, then you have
    > half swapped objects.


    But what is the alternative? Suppressing any errors and have an
    erroneous state without a chance of knowing?
     
    Eberhard Schefold, Jun 15, 2007
    #4
  5. Jess

    ppi Guest

    On Jun 15, 10:37 am, dasjotre <> wrote:
    > On 15 Jun, 13:21, Jess <> wrote:
    >
    > > Hello,

    >
    > > It is said that if I implement a "swap" member function, then it
    > > should never throw any exception. However, if I implement "swap" non-
    > > member function, then the restriction doesn't apply. Can somebody tell
    > > me why?

    >
    > I think that the restriction must apply regardless to whether it is
    > member or not.
    >
    > consider
    >
    > struct A
    > {
    > T1 t1_;
    > T2 t2_;
    >
    > };
    >
    > void swap(A & l, A & r)
    > {
    > swap(l.t1, r.t1);
    > swap(l.t2, r.t2);
    >
    > }
    >
    > and second swap throws, then you have
    > half swapped objects.
    >
    > regards
    >
    > DS


    swap members should not throw, since most of the times these are the
    method used to build a correct operator=(). If swap throws it's
    impossible to get operator=() to work properly.
    I think H.Sutter wrote about it in one of its books (dunno if you can
    find someting in gotw though):

    T& operator=( const T& src )
    {
    T temp(src); // can throw
    this->swap( temp );// PLZ do not throw !
    return *this;// will not throw
    }

    If swap throws, we end-up with an ill-formed object, its members state
    is unknown.
    if the construction of the temp throws it's ok, operator= failed, but
    the object is in a clean state - nothing happened.

    swap defined outside classes have other purposes, they can carry
    business logic with them, they are allowed to throw most of the time.

    They do have have the same name, but their purpose are slightly
    different.
    Hope this will help.

    Cheers,
    paulo
     
    ppi, Jun 15, 2007
    #5
  6. Jess

    Puppet_Sock Guest

    On Jun 15, 10:44 am, Eberhard Schefold
    [snip]
    > But what is the alternative? Suppressing any errors and have an
    > erroneous state without a chance of knowing?


    I think it should probably be "commit or roll back"
    not "no throws." That is to say, the code should
    be constructed such that it can't leave the data
    in an unpredictable state. It should either work
    correctly or leave the data in the state it was.

    For tiny objects being swapped you can be fairly
    confident that you won't get an error. Except maybe
    a stack problem if you happened to be *right* at the
    edge and put one more automatic on there.

    But I'm not sure you *can* promise no throws when
    you are talking about larger objects being swapped.
    Consider, just as an example, you may be required
    to do an assign of one object to another to do the
    swap. And that might call new, and that might get
    you to the end of the freestore. Or fail on some
    other resource.
    Socks
     
    Puppet_Sock, Jun 15, 2007
    #6
  7. Jess

    dasjotre Guest

    On 15 Jun, 15:44, Eberhard Schefold <>
    wrote:
    > dasjotre wrote:
    > > void swap(A & l, A & r)
    > > {
    > > swap(l.t1, r.t1);
    > > swap(l.t2, r.t2);
    > > }

    >
    > > and second swap throws, then you have
    > > half swapped objects.

    >
    > But what is the alternative? Suppressing any errors and have an
    > erroneous state without a chance of knowing?


    if you mean try {}catch(...){ do nothing } I agree completely.
    it is 'no solution'

    you could use PIMPL, swap then becomes
    just a swap of pointers and I can not think
    of a case when that failed ;)

    regards

    DS
     
    dasjotre, Jun 15, 2007
    #7
  8. Jess

    dasjotre Guest

    On 15 Jun, 15:48, ppi <> wrote:
    > I think H.Sutter wrote about it in one of its books (dunno if you can
    > find someting in gotw though):


    indeed
    http://www.gotw.ca/gotw/059.htm

    regards

    DS
     
    dasjotre, Jun 15, 2007
    #8
  9. On Fri, 15 Jun 2007 05:21:10 -0700, Jess wrote:
    >It is said that if I implement a "swap" member function, then it
    >should never throw any exception.


    This may be a recommendation but it's not a fixed requirement. You can
    use the exception specification throw() to guarantee that no exception
    is thrown from a function.

    >However, if I implement "swap" non-
    >member function, then the restriction doesn't apply. Can somebody tell
    >me why?


    You probably mean a specialization for std::swap() here. AFAIK, there
    are no restrictions WRT exceptions for std::swap().


    --
    Roland Pibinger
    "The best software is simple, elegant, and full of drama" - Grady Booch
     
    Roland Pibinger, Jun 15, 2007
    #9
  10. Jess

    Daniel T. Guest

    Eberhard Schefold <> wrote:
    > dasjotre wrote:
    >
    > > void swap(A & l, A & r)
    > > {
    > > swap(l.t1, r.t1);
    > > swap(l.t2, r.t2);
    > > }
    > >
    > > and second swap throws, then you have
    > > half swapped objects.

    >
    > But what is the alternative? Suppressing any errors and have an
    > erroneous state without a chance of knowing?


    There is no reason for a swap to fail (other than truly incredible
    circumstances that can't be detected before hand in any case.)
     
    Daniel T., Jun 15, 2007
    #10
  11. Jess

    Daniel T. Guest

    Puppet_Sock <> wrote:
    > On Jun 15, 10:44 am, Eberhard Schefold


    > > But what is the alternative? Suppressing any errors and have an
    > > erroneous state without a chance of knowing?

    >
    > I think it should probably be "commit or roll back" not "no throws."
    > That is to say, the code should be constructed such that it can't
    > leave the data in an unpredictable state. It should either work
    > correctly or leave the data in the state it was.
    >
    > For tiny objects being swapped you can be fairly confident that you
    > won't get an error. Except maybe a stack problem if you happened to
    > be *right* at the edge and put one more automatic on there.
    >
    > But I'm not sure you *can* promise no throws when you are talking
    > about larger objects being swapped.


    Larger objects are just collections of tiny objects. There is no
    reason for a large object swap to fail either.

    > Consider, just as an example, you may be required to do an assign of
    > one object to another to do the swap.


    Maybe an example would help?
     
    Daniel T., Jun 15, 2007
    #11
  12. Jess

    Andre Kostur Guest

    (Roland Pibinger) wrote in news:4672bdfb.9209182
    @news.utanet.at:

    > On Fri, 15 Jun 2007 05:21:10 -0700, Jess wrote:
    >>It is said that if I implement a "swap" member function, then it
    >>should never throw any exception.

    >
    > This may be a recommendation but it's not a fixed requirement. You can
    > use the exception specification throw() to guarantee that no exception
    > is thrown from a function.


    Um. No. throw() says that you don't intend for exceptions to be
    thrown/escape from that function... but in reality, should an exception end
    up attempting to escape from that function, all that will do it convert
    that exception into a std::bad_exception. So specifying throw() doesn't
    guarantee that there will be no exceptions in that function.
     
    Andre Kostur, Jun 15, 2007
    #12
  13. Jess

    Pete Becker Guest

    Andre Kostur wrote:
    > (Roland Pibinger) wrote in news:4672bdfb.9209182
    > @news.utanet.at:
    >
    >> On Fri, 15 Jun 2007 05:21:10 -0700, Jess wrote:
    >>> It is said that if I implement a "swap" member function, then it
    >>> should never throw any exception.

    >> This may be a recommendation but it's not a fixed requirement. You can
    >> use the exception specification throw() to guarantee that no exception
    >> is thrown from a function.

    >
    > Um. No. throw() says that you don't intend for exceptions to be
    > thrown/escape from that function... but in reality, should an exception end
    > up attempting to escape from that function, all that will do it convert
    > that exception into a std::bad_exception. So specifying throw() doesn't
    > guarantee that there will be no exceptions in that function.
    >


    You won't ever get any exception whose type is not listed in the throw
    specifier.

    If an exception is thrown that doesn't match the throw specifier, the
    implementation calls unexpected(). The default behavior of unexpected()
    is to call terminate().

    Your application can replace the unexpected handler by calling
    set_unexpected with the address of a suitable handler function. The
    handler function isn't allowed to return. It can call terminate(), it
    can throw another exception object, or it can rethrow the object that
    was thrown. If it throws an exception whose type is one of the types
    listed in the throw specifier, then unwinding continues. If it throws an
    exception whose type is not listed in the throw specifier AND the list
    of types in the throw specifier includes std::bad_exception, the thrown
    exception object is replaced by an object of type std::bad_exception. If
    the list of types in the throw specifier does not include
    std::bad_exception, the implementation calls terminate().

    The details are in [except.unexpected]. They're summarized in the third
    paragraph of that section:

    Thus, an exception-specification guarantees that only
    the listed exceptions will be thrown. If the
    exception-specification includes the type std::bad_exception
    then any exception not on the list may be replaced by
    std::bad_exception within the function std::unexpected().

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
     
    Pete Becker, Jun 15, 2007
    #13
  14. Jess

    Puppet_Sock Guest

    On Jun 15, 12:39 pm, "Daniel T." <> wrote:
    > Puppet_Sock <> wrote:
    > > On Jun 15, 10:44 am, Eberhard Schefold
    > > > But what is the alternative? Suppressing any errors and have an
    > > > erroneous state without a chance of knowing?

    >
    > > I think it should probably be "commit or roll back" not "no throws."
    > > That is to say, the code should be constructed such that it can't
    > > leave the data in an unpredictable state. It should either work
    > > correctly or leave the data in the state it was.

    >
    > > For tiny objects being swapped you can be fairly confident that you
    > > won't get an error. Except maybe a stack problem if you happened to
    > > be *right* at the edge and put one more automatic on there.

    >
    > > But I'm not sure you *can* promise no throws when you are talking
    > > about larger objects being swapped.

    >
    > Larger objects are just collections of tiny objects. There is no
    > reason for a large object swap to fail either.


    Um. I'm not altogether sure I agree with the intent of that.
    An object with a file handle isn't *just* a collection of
    smaller objects. An object with a pointer to memory that
    the object allocated isn't *just* a collection of smaller
    objects. Both of these are also "managers" of other data.
    That data may or may not get copied if the object is copied,
    may (probably) or may not get swapped if the objects are.

    > > Consider, just as an example, you may be required to do an assign of
    > > one object to another to do the swap.

    >
    > Maybe an example would help?


    Consider a swap based on the tired old temp object.

    // fill in the function header stuff as usual
    myClass tmp; // 1
    tmp = a; // 2
    a = b; // 3
    b = tmp; // 4

    The "function header stuff" could, in principle,
    blow the stack. Don't know if a try-catch can
    solve that little problem, but let's move on.

    Line 1 could involve calls to new, and so could fail.
    It's not likely to fail for built in things like ints.
    Though it could blow the stack if you were right at
    the edge. I seem to recall saying that. Again, I don't
    know what a try-catch would do for you in that case.

    But if myClass's default ctor involves a call to new,
    it could easily blow the freestore. Or, if some other
    resource is involved, that could throw. Say it needs a
    temp file or something. Maybe the system runs out of
    file handles, or the disk is full, or the network times
    out or some silly thing.

    Line 2 might also involve calls to new, or allocating
    resources. Maybe myClass's default ctor just allocates
    some stub or something, then the copy does a deep
    copy. So now, tmp has to have a copy of all of a's
    resources. That might blow the freestore.

    Line 3, same thing, particularly if b is lots bigger
    than a. And line 4, again, same thing, particularly if
    a is lots bigger than b.

    I don't think it's possible to do these operations in
    such a way that it's not possible for a throw. It is
    possible to do them, with some effort, such that there
    won't be an unpredictable data state. Either the swap
    will work, or an exception gets thrown and the data
    goes back to where it was before the operation started.
    Socks
     
    Puppet_Sock, Jun 15, 2007
    #14
  15. Jess

    Daniel T. Guest

    Puppet_Sock <> wrote:

    > > Larger objects are just collections of tiny objects. There is no
    > > reason for a large object swap to fail either.

    >
    > Um. I'm not altogether sure I agree with the intent of that.
    > An object with a file handle isn't *just* a collection of
    > smaller objects.


    Well no, in that case it is a simple pointer, swapping them is a
    no-brainer.

    > An object with a pointer to memory that
    > the object allocated isn't *just* a collection of smaller
    > objects.


    Again, you are simply swapping two pointers.

    > > > Consider, just as an example, you may be required to do an assign of
    > > > one object to another to do the swap.

    > >
    > > Maybe an example would help?

    >
    > Consider a swap based on the tired old temp object.
    >
    > // fill in the function header stuff as usual
    > myClass tmp; // 1
    > tmp = a; // 2
    > a = b; // 3
    > b = tmp; // 4
    >
    > The "function header stuff" could, in principle,
    > blow the stack. Don't know if a try-catch can
    > solve that little problem, but let's move on.
    >
    > Line 1 could involve calls to new, and so could fail.

    [...]
    > Line 2 might also involve calls to new, or allocating
    > resources.

    [...]
    > Line 3, same thing, particularly if b is lots bigger
    > than a.


    Then provide a swap member-function that doesn't do that. Someone else
    has already provided a link to the GotW article that shows that, in
    principle, any class can provide an exception safe swap function. This
    is old ground.
     
    Daniel T., Jun 15, 2007
    #15
  16. Jess

    Andre Kostur Guest

    Pete Becker <> wrote in
    news::

    > Andre Kostur wrote:
    >> (Roland Pibinger) wrote in news:4672bdfb.9209182
    >> @news.utanet.at:
    >>
    >>> On Fri, 15 Jun 2007 05:21:10 -0700, Jess wrote:
    >>>> It is said that if I implement a "swap" member function, then it
    >>>> should never throw any exception.
    >>> This may be a recommendation but it's not a fixed requirement. You
    >>> can use the exception specification throw() to guarantee that no
    >>> exception is thrown from a function.

    >>
    >> Um. No. throw() says that you don't intend for exceptions to be
    >> thrown/escape from that function... but in reality, should an
    >> exception end up attempting to escape from that function, all that
    >> will do it convert that exception into a std::bad_exception. So
    >> specifying throw() doesn't guarantee that there will be no exceptions
    >> in that function.
    >>

    >
    > You won't ever get any exception whose type is not listed in the throw
    > specifier.
    >
    > If an exception is thrown that doesn't match the throw specifier, the
    > implementation calls unexpected(). The default behavior of
    > unexpected() is to call terminate().
    >
    > Your application can replace the unexpected handler by calling
    > set_unexpected with the address of a suitable handler function. The
    > handler function isn't allowed to return. It can call terminate(), it
    > can throw another exception object, or it can rethrow the object that
    > was thrown. If it throws an exception whose type is one of the types
    > listed in the throw specifier, then unwinding continues. If it throws
    > an exception whose type is not listed in the throw specifier AND the
    > list of types in the throw specifier includes std::bad_exception, the
    > thrown exception object is replaced by an object of type
    > std::bad_exception. If the list of types in the throw specifier does
    > not include std::bad_exception, the implementation calls terminate().
    >
    > The details are in [except.unexpected]. They're summarized in the
    > third paragraph of that section:
    >
    > Thus, an exception-specification guarantees that only
    > the listed exceptions will be thrown. If the
    > exception-specification includes the type std::bad_exception
    > then any exception not on the list may be replaced by
    > std::bad_exception within the function std::unexpected().
    >



    Apparently my memory is bad. I thought it was always translated to
    std::bad_exception.
     
    Andre Kostur, Jun 15, 2007
    #16
  17. Jess

    James Kanze Guest

    On Jun 15, 2:21 pm, Jess <> wrote:

    > It is said that if I implement a "swap" member function, then it
    > should never throw any exception. However, if I implement "swap" non-
    > member function, then the restriction doesn't apply. Can somebody tell
    > me why?


    More convention that anything else. A non-member function can
    usually not to much else but to use the conventional algorithm:

    T tmp( a ) ;
    a = b ;
    b = tmp ;

    This involves constructing a new object (the tmp), which can
    often throw. A member function, however, has access to the
    underlying types: pointers, etc., and can usually avoid deep
    copy by just swapping the pointers. This is not only
    significantly faster in some cases, but swapping two pointers,
    even with the above algorithm, will not throw.

    Being able to swap without throwing means that we can
    effectively copy without throwing: if I have something like:

    T x, y ;
    x.swap( y ) ;

    has the same effect on x as copying y into x, except that a real
    copy might throw (since it would deep copy all of y---here that
    is avoided by allowing y to become a copy of x, effectively
    swapping ownership of any resources, rather than allocating them
    new).

    This is in turn very useful for things like operator=. Consider
    an object that uses the compilation firewall idiom:

    // Classical op=
    T&
    T::eek:perator=( T const& rhs )
    {
    if ( this != &rhs ) {
    delete pImpl ;
    pImpl = new Impl( *rhs.pImpl ) ;
    // What happens if the above line throws???
    }
    return *this ;
    }

    // Using swap.
    T&
    T::eek:perator=( T const& rhs )
    {
    T tmp( rhs ) ; // Actual copy, and possible throw,
    // occurs here.
    std::swap( tmp.pImpl, pImpl ) ;
    // Now this is the actual copy, and
    // tmp holds all our old resources.
    return *this ; // Destructs tmp, thus freeing our
    // old resources.
    }

    Of course, this can be done without swap; I could have just
    copied the impl into a temporary pointer, deleted my pImpl, and
    then assigned it with the results of the copy. (Which is still
    the way I write something as simple as the compilation firewall
    idiom.) Doing it this way becomes a bit more complicated,
    however, when I have more members, all of which need the same
    treatment. And since I'm actually swapping, why not make the
    function available at the public interface level? That way, a
    class which doesn't use the compilation firewall idiom, but uses
    an instance of my class, can easily implement its own no-throw
    version of swap. The benefit propagates.

    Note, however, that all of this concerning swap is just a means
    to an end, and in no way necessary. The important thing isn't
    swap; it's having an assignment operator that doesn't leave the
    object in an undefined state if copying something in it throws.
    Having a no-throw version of swap is just a convenient and
    conventional method of ensuring that this is posssible, and in
    fact rather easy.

    --
    James Kanze (Gabi Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 16, 2007
    #17
  18. Jess

    James Kanze Guest

    On Jun 15, 4:53 pm, Puppet_Sock <> wrote:
    > On Jun 15, 10:44 am, Eberhard Schefold
    > [snip]


    > > But what is the alternative? Suppressing any errors and have an
    > > erroneous state without a chance of knowing?


    > I think it should probably be "commit or roll back"
    > not "no throws." That is to say, the code should
    > be constructed such that it can't leave the data
    > in an unpredictable state. It should either work
    > correctly or leave the data in the state it was.


    Those last two statements say different things, and the last is
    often more than you need. Depending on the application, a
    simple guarantee that the object can be destructed may be
    enough. But even that's not obvious unless you are careful.

    > For tiny objects being swapped you can be fairly
    > confident that you won't get an error. Except maybe
    > a stack problem if you happened to be *right* at the
    > edge and put one more automatic on there.


    > But I'm not sure you *can* promise no throws when
    > you are talking about larger objects being swapped.


    The whole point of having a member function is that it can swap
    the resources, rather than reallocating them to make a deep
    copy, as a non-member would have to. When I use the swap idiom
    in an assignment operator, for example, I use std::swap for the
    built in types, and a member function swap for class types. If
    any of the types involved is a class without a member function
    swap, I presume that it cannot be swapped without exceptions,
    and that the classical swap assignment operator cannot be used.

    > Consider, just as an example, you may be required
    > to do an assign of one object to another to do the
    > swap. And that might call new, and that might get
    > you to the end of the freestore. Or fail on some
    > other resource.


    It's always possible to write a no throw swap if you control all
    of the classes involved. A member swap function swaps all of
    the elements, using a global swap for non class types (for which
    the generic std::swap cannot throw), and a member swap for class
    types (which is written in the same vein). Recursively, we
    always end up with built-in types (maybe pointers), which can be
    swapped without throwing.

    --
    James Kanze (Gabi Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 16, 2007
    #18
  19. Jess

    James Kanze Guest

    On Jun 15, 9:47 pm, "Daniel T." <> wrote:

    [...]
    > Then provide a swap member-function that doesn't do that. Someone else
    > has already provided a link to the GotW article that shows that, in
    > principle, any class can provide an exception safe swap function. This
    > is old ground.


    The statement that "any class can provide an exception safe swap
    function" isn't true. The statement should be that any class
    which consists of only non-class types or class types which
    provide an exception safe swap function can provide an exception
    safe swap function. If you control all of the classes involved,
    this is not a problem; if you encounter an element of a class
    type which doesn't provide an exception safe swap function, you
    add it to that class, ad infitum, until you reach non class
    types. If you don't have that control, i.e. you are using third
    party libraries which you cannot modify, it may not be possible
    to provide a no throw swap function. And in the same way that
    the possibility can propagate through your code, the
    impossibility propagates up.

    --
    James Kanze (Gabi Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 16, 2007
    #19
  20. Jess

    Daniel T. Guest

    James Kanze <> wrote:
    > On Jun 15, 9:47 pm, "Daniel T." <> wrote:
    >
    > > Then provide a swap member-function that doesn't do that. Someone else
    > > has already provided a link to the GotW article that shows that, in
    > > principle, any class can provide an exception safe swap function. This
    > > is old ground.

    >
    > The statement that "any class can provide an exception safe swap
    > function" isn't true.


    Any class can, in principle, be written using the pimpl idiom, and a
    class using the pimpl idiom can always provide an exception safe swap.

    > The statement should be that any class
    > which consists of only non-class types or class types which
    > provide an exception safe swap function can provide an exception
    > safe swap function. If you control all of the classes involved,
    > this is not a problem;


    You don't need to control all the classes involved... simply write your
    class using a single pointer as a member. That way your class will
    consist "of only non-class types".
     
    Daniel T., Jun 16, 2007
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kerri
    Replies:
    2
    Views:
    13,035
    Kevin Spencer
    Oct 27, 2003
  2. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,995
    Smokey Grindel
    Dec 2, 2006
  3. Joe Van Dyk
    Replies:
    4
    Views:
    333
    Joe Van Dyk
    Apr 10, 2006
  4. Niels Dekker (no reply address)

    What swap is called when using std::swap?

    Niels Dekker (no reply address), Jul 19, 2006, in forum: C++
    Replies:
    4
    Views:
    993
    Niels Dekker (no reply address)
    Jul 20, 2006
  5. Andrew Walrond
    Replies:
    6
    Views:
    96
    Ara.T.Howard
    Jun 29, 2004
Loading...

Share This Page