Matteo Settenvini <[email protected]> writes:
> Murray Cumming <[email protected]> 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
[email protected]
https://mail.gnome.org/mailman/listinfo/gtkmm-list