
On 3 April 2012 10:44, Dave Abrahams <dave@boostpro.com> wrote:
But isn't this a better way to relieve the tedium?
#define RETURNS(...) \ noexcept(noexcept(decltype(__VA_ARGS__)(std::move(__VA_ARGS__)))) \ -> decltype(__VA_ARGS__) \ { return (__VA_ARGS__); } \ typedef int RETURNS_CAT(RETURNS_, __LINE__)
#define RETURNS_CAT_0(x, y) x ## y #define RETURNS_CAT(x, y) RETURNS_CAT_0(x,y)
...
auto swap(B& x, B& y) RETURNS(swap(x.a,y.a), swap(x.b,y.b), ...);
But is that really allowed? I could not get it to work on clang because the declaration of swap needs access to the members of the class and the class definition is incomplete at that point. Moving the definition of swap outside the class did not help because you need access to private members. Making swap friend also does not help because friend declaration also needs a matching noexcept specification. gcc 4.7 seems to be lenient regarding this check but clang is not. Alternatively, using std::tuple could help in reducing verbosity of noexcept specification Howard is alluding to. template<typename... T> struct is_nothrow_swappable_all { static std::tuple<T...> *t; enum { value = noexcept(t->swap(*t)) }; }; Assuming all members and bases are swapped using std::swap something like the following could be used. using namespace std; struct Base { ... }; // Assuming Base has a std::swap<Base> specialization class Test : struct Base { string str; complex<double> cd; map<int, string> m; public: void swap(Test &) noexcept(is_nothrow_swappable_all<Base, string, complex<double>, map<int, string>>::value) { ... } }; However, I don't think if we could use std::make_tuple to avoid spelling out types all over again due to the reasons mentioned above. I would love to stand corrected. Sumant