Matteo Settenvini <mat...@member.fsf.org> writes:

> Murray Cumming <murr...@murrayc.com> writes:
>
>> And, should we implement swap() using std::swap() on the member
>> variables, or even std::move() on the member variables?
>
> It depends. If everything is noexcept, I'd say it's quite the same. If
> something can throw an exception, it needs to be done by e.g. swapping
> tuples, so that it is guaranteed that the object is not left in an
> inconsistent state. For instance, this is dangerous [1]:
>
> void C::swap(C& that)
> {
>     using std::swap; // needed to allow Koenig lookup rules to apply
>     swap(this->a, that.a);
>     swap(this->b, that.b); // throws
>     swap(this->c, that.c);
> }
>
> Then when catching the exception, "this" and "that" will have had their
> first member swapped, but not the other two fields.
>

I wanted to follow up my previous post with a simpler solution using
variadic templates. This makes relatively easy to implement a safer
version of swap with rollback semantics.

Code follows.

Cheers,
Matteo


#include <exception>
#include <iostream>
#include <tuple>
#include <utility>

inline void
safer_swap ()
{
        return;    
}

template<typename T, typename... Rest>
inline void
safer_swap (T& a, T& b, Rest... cdr)
{
        using std::swap;
        swap (a, b);
        try
        {
                safer_swap (cdr...);
        }
        catch (...)
        {
                swap (a, b);
                throw;
        }
}


namespace ns
{
        class Throwing
        {
        public:
                Throwing() = default;

                Throwing(const Throwing&)
                {
                        throw std::runtime_error("");
                }
        };


        class Swapper
        {
        public:
                int a;
                Throwing b;
                int c;

                void swap(Swapper& that)
                {
                        safer_swap (a, that.a,
                                    b, that.b,
                                    c, that.c);
                }       
        };
        
} // ~ namespace ns;


namespace std
{
        template<>
        void swap(::ns::Swapper& a, ::ns::Swapper& b)
             noexcept(noexcept(a.swap(b)))
        {
                a.swap(b);
        }

}


int 
main()
{
        ns::Swapper a, b;
        a.a = a.c = 1; 
        b.a = b.c = 2;
        try
        {
                std::swap(a, b);
        }
        catch(std::runtime_error&)
        {
                std::cout << "(" << a.a << ", " << a.c << ") vs. "
                          << "(" << b.a << ", " << b.c << ")" << std::endl;
        }
}


_______________________________________________
gtkmm-list mailing list
gtkmm-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtkmm-list

Reply via email to