Boost logo

Boost :

Subject: Re: [boost] C++11 Metaprogramming
From: Sumant Tambe (sutambe_at_[hidden])
Date: 2012-04-04 22:31:06

On 3 April 2012 10:44, Dave Abrahams <dave_at_[hidden]> 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;
  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.


Boost list run by bdawes at, gregod at, cpdaniel at, john at