$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r81067 - sandbox/variadic_templates/sandbox/slim/test
From: cppljevans_at_[hidden]
Date: 2012-10-26 08:54:40
Author: cppljevans
Date: 2012-10-26 08:54:38 EDT (Fri, 26 Oct 2012)
New Revision: 81067
URL: http://svn.boost.org/trac/boost/changeset/81067
Log:
Added tuple implementations from boostcon 2012:
https://github.com/ericniebler/home/tree/master/src/tuple
after extracting relevant parts into tuple_impl_bcon12*.hpp
files.
Added:
   sandbox/variadic_templates/sandbox/slim/test/tuple.benchmark.mini.time.txt   (contents, props changed)
   sandbox/variadic_templates/sandbox/slim/test/tuple.test.cpp   (contents, props changed)
   sandbox/variadic_templates/sandbox/slim/test/tuple_impl_bcon12_horizontal.hpp   (contents, props changed)
   sandbox/variadic_templates/sandbox/slim/test/tuple_impl_bcon12_vertical.hpp   (contents, props changed)
Text files modified: 
   sandbox/variadic_templates/sandbox/slim/test/Makefile                 |    13 +++++++------                           
   sandbox/variadic_templates/sandbox/slim/test/macros.benchmark.pp.hpp  |     1 -                                       
   sandbox/variadic_templates/sandbox/slim/test/tuple.benchmark.mini.cpp |     8 ++++----                                
   sandbox/variadic_templates/sandbox/slim/test/tuple_benchmark_run.py   |    15 ++++++++++-----                         
   4 files changed, 21 insertions(+), 16 deletions(-)
Modified: sandbox/variadic_templates/sandbox/slim/test/Makefile
==============================================================================
--- sandbox/variadic_templates/sandbox/slim/test/Makefile	(original)
+++ sandbox/variadic_templates/sandbox/slim/test/Makefile	2012-10-26 08:54:38 EDT (Fri, 26 Oct 2012)
@@ -1,23 +1,24 @@
 MAIN=test
 BENCHMARK=mini
+BENCHMARK=tree_builder
 MAIN=tuple.benchmark.$(BENCHMARK)
+MAIN=tuple.test
 MEASURE=time
 THISFILE=Makefile
 PYTHON=python3.1
 
+HOW=gcc4_8_20120624
+#HOW=clangxx_rel
 DIR.root := $(shell dirup_dir_file.pl $(PWD) root.imk)
 include $(DIR.root)/root.imk
 #include compiler_macros.imk
 
-HOW=gcc4_8n
-HOW=clangxx_rel
-
 HOWS=gcc4_8n clangxx
 
 SLIM_DIR=../slim/include 
 #INCS:= -I$(SLIM_DIR) $(INCS)
 
-BFLAGS=-DTUPLE_SIZE=4 -DLAST_LESS=2 -DTUPLE_IMPL=tuple_impl_std.hpp -DTUPLE_CHUNK=4
+BFLAGS=-DTUPLE_SIZE=4 -DLAST_LESS=2 -DTUPLE_IMPL=tuple_impl_bcon12_vertical.hpp -DTUPLE_CHUNK=4
 BFNAME:=$(shell ./flags2filename.pl -S $(BFLAGS))
 PROF_BASE=$(MAIN).$(HOW).$(BFNAME)
 COMPILER.clangxx_ins-rt=$(PATH.llvm.top)/llvm/projects/compiler-rt
@@ -141,6 +142,6 @@
 echo:
         @echo "SHELL="$(SHELL)
 
-.PHONY: python
-python:
+.PHONY: benchmark_run
+benchmark_run:
         $(PYTHON) tuple_benchmark_run.py
Modified: sandbox/variadic_templates/sandbox/slim/test/macros.benchmark.pp.hpp
==============================================================================
--- sandbox/variadic_templates/sandbox/slim/test/macros.benchmark.pp.hpp	(original)
+++ sandbox/variadic_templates/sandbox/slim/test/macros.benchmark.pp.hpp	2012-10-26 08:54:38 EDT (Fri, 26 Oct 2012)
@@ -1,7 +1,6 @@
 #if !defined(TUPLE_SIZE)
   //This only used when not running several benchmarks where
   //macro values are set on command line with -DMACRO=VALUE.
-  //See tuple.benchmark.mk.
   #define TUPLE_IMPL tuple_impl_horizontal.hpp
     //TUPLE_TEST_IMPL selects the tuple implementation method.
     //TUPLE_TEST_VERTICAL selects the preprocessor generated
Modified: sandbox/variadic_templates/sandbox/slim/test/tuple.benchmark.mini.cpp
==============================================================================
--- sandbox/variadic_templates/sandbox/slim/test/tuple.benchmark.mini.cpp	(original)
+++ sandbox/variadic_templates/sandbox/slim/test/tuple.benchmark.mini.cpp	2012-10-26 08:54:38 EDT (Fri, 26 Oct 2012)
@@ -45,11 +45,11 @@
 };
 
 template<int I,int J, int Max, typename... Args>
-struct make_tuple:
-	make_tuple<I,J,Max-1,int_value<I*TUPLE_SIZE*TUPLE_SIZE+J*TUPLE_SIZE+Max>,Args...>
+struct mk_tuple_col_row:
+	mk_tuple_col_row<I,J,Max-1,int_value<I*TUPLE_SIZE*TUPLE_SIZE+J*TUPLE_SIZE+Max>,Args...>
 {};
 template<int I,int J, typename... Args>
-struct make_tuple<I,J,0, Args...>
+struct mk_tuple_col_row<I,J,0, Args...>
 {
         typedef tuple_bench<Args...> type;
 };
@@ -63,7 +63,7 @@
 struct test_row
 {
  private:
-	typedef typename make_tuple<I, J, TUPLE_SIZE>::type tuple_type;
+	typedef typename mk_tuple_col_row<I, J, TUPLE_SIZE>::type tuple_type;
 
         template<int K>
         static int at_test(tuple_type& t,int_key<K>)
Added: sandbox/variadic_templates/sandbox/slim/test/tuple.benchmark.mini.time.txt
==============================================================================
--- (empty file)
+++ sandbox/variadic_templates/sandbox/slim/test/tuple.benchmark.mini.time.txt	2012-10-26 08:54:38 EDT (Fri, 26 Oct 2012)
@@ -0,0 +1,72 @@
+compiler= clangxx
+version={
+clang version 3.2 (trunk 165317)
+Target: x86_64-unknown-linux-gnu
+Thread model: posix
+compiler_exe= /home/evansl/download/llvm/svn/build/Release/bin/clang
+}
+['compiler', 'TUPLE_IMPL', 'TUPLE_SIZE', 'LAST_LESS', 'TUPLE_CHUNK']
+['clangxx', 'horizontal', 10, 4, -1]
+{
+user:0.26 system:0.00 elapsed:0.25
+}
+['clangxx', 'horizontal', 20, 4, -1]
+{
+user:0.42 system:0.06 elapsed:0.47
+}
+['clangxx', 'horizontal', 30, 4, -1]
+{
+user:0.60 system:0.10 elapsed:0.69
+}
+['clangxx', 'horizontal', 40, 4, -1]
+{
+user:0.86 system:0.08 elapsed:0.93
+}
+['clangxx', 'bcon12_horizontal', 10, 4, -1]
+{
+user:0.53 system:0.03 elapsed:0.55
+}
+['clangxx', 'bcon12_horizontal', 20, 4, -1]
+{
+user:0.75 system:0.08 elapsed:0.82
+}
+['clangxx', 'bcon12_horizontal', 30, 4, -1]
+{
+user:1.00 system:0.11 elapsed:1.10
+}
+['clangxx', 'bcon12_horizontal', 40, 4, -1]
+{
+user:1.30 system:0.11 elapsed:1.40
+}
+['clangxx', 'vertical', 10, 4, 10]
+{
+user:0.24 system:0.04 elapsed:0.33
+}
+['clangxx', 'vertical', 20, 4, 10]
+{
+user:0.40 system:0.02 elapsed:0.41
+}
+['clangxx', 'vertical', 30, 4, 10]
+{
+user:0.56 system:0.05 elapsed:0.60
+}
+['clangxx', 'vertical', 40, 4, 10]
+{
+user:0.74 system:0.07 elapsed:0.80
+}
+['clangxx', 'bcon12_vertical', 10, 4, -1]
+{
+user:0.45 system:0.05 elapsed:0.49
+}
+['clangxx', 'bcon12_vertical', 20, 4, -1]
+{
+user:0.63 system:0.04 elapsed:0.66
+}
+['clangxx', 'bcon12_vertical', 30, 4, -1]
+{
+user:0.76 system:0.11 elapsed:0.86
+}
+['clangxx', 'bcon12_vertical', 40, 4, -1]
+{
+user:0.98 system:0.08 elapsed:1.05
+}
Added: sandbox/variadic_templates/sandbox/slim/test/tuple.test.cpp
==============================================================================
--- (empty file)
+++ sandbox/variadic_templates/sandbox/slim/test/tuple.test.cpp	2012-10-26 08:54:38 EDT (Fri, 26 Oct 2012)
@@ -0,0 +1,88 @@
+//Acknowlegements:
+//  The following code was adapted from part of the code in
+//    https://github.com/ericniebler/home/blob/master/src/tuple/unrolled_tuple.hpp
+//ChangeLog:
+//  2012-10-26 LJ Evans
+//    1) Copied the code after the line:
+//        #ifdef TEST
+//       in the above mentioned unrolled_tuple.hpp file.
+//    2) Added the boostpp #includes.
+//    3) Used the boostpp stringize to #include the tuple implementation code
+//       named by a macro.
+//
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2012 Eric Niebler.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <boost/preprocessor/stringize.hpp>
+#ifndef TUPLE_IMPL
+#define TUPLE_IMPL tuple_impl_bcon12_vertical.hpp
+#endif
+#include BOOST_PP_STRINGIZE(TUPLE_IMPL)
+
+#include <cstdio>
+//////////////////////////////////////////////////////
+//{copied from unrolled_tuple.hpp:
+
+struct S
+{
+    S() { std::printf("not constexpr!\n"); }
+};
+
+// What is a literal type?
+
+constexpr tuple_bench<> t0{};
+static_assert(std::is_trivial<tuple_bench<>>::value, "not trivial");
+
+constexpr tuple_bench<int> t1{42};
+static_assert(std::is_trivial<tuple_bench<int>>::value, "not trivial");
+
+constexpr tuple_bench<int, float> t2{1, 3.14f};
+static_assert(std::is_trivial<tuple_bench<int, float>>::value, "not trivial");
+
+constexpr tuple_bench<int, tuple_bench<int, float>> t3{1, tuple_bench<int, float>{2, 3.14f}};
+static_assert(std::is_trivial<tuple_bench<int, tuple_bench<int, float>>>::value, "not trivial");
+
+constexpr int i = get<0>(t1);
+static_assert(i == 42, "not a compile-time constant");
+
+constexpr float f = get<1>(t2);
+static_assert(f == 3.14f, "not a compile-time constant");
+
+//static_assert(std::is_same<int, tuple_bench_element<0, tuple_bench<int>>::type>::value, "wrong element");
+//static_assert(std::is_same<float &, tuple_bench_element<1, tuple_bench<int, float &>>::type>::value, "wrong element");
+
+// Make sure I understand how decltype, rvalues and lvalues work.
+struct T { S s; };
+static_assert(!std::is_reference<decltype((T().s))>::value, "not is rvalue ref");
+static_assert(std::is_reference<decltype((static_cast<T &&>(T()).s))>::value, "is rvalue ref");
+static_assert(!std::is_lvalue_reference<decltype((static_cast<T &&>(T()).s))>::value, "is lvalue ref");
+
+void test()
+{
+    tuple_bench<S> s,t;
+    t = s;
+    S &ss = get<0>(s);
+    get<0>(s) = get<0>(t);
+    S && sss = get<0>(::make_tuple(S()));
+    static_assert(std::is_reference<decltype(get<0>(::make_tuple(S())))>::value, "");
+    static_assert(!std::is_lvalue_reference<decltype(get<0>(::make_tuple(S())))>::value, "");
+
+    int i = 0;
+    tuple_bench<int &> ti{i};
+    tuple_bench<int &> ti2(ti);
+    static_assert(std::is_lvalue_reference<decltype(get<0>(ti2))>::value, "");
+
+    static_assert(sizeof(tuple_bench<char,char,char>)==3, "wrong size");
+
+    std::printf("%f\n", (double)f);;
+}
+//}copied from unrolled_tuple.hpp:
+
+int main()
+{
+    test();
+    return 0;
+}    
Modified: sandbox/variadic_templates/sandbox/slim/test/tuple_benchmark_run.py
==============================================================================
--- sandbox/variadic_templates/sandbox/slim/test/tuple_benchmark_run.py	(original)
+++ sandbox/variadic_templates/sandbox/slim/test/tuple_benchmark_run.py	2012-10-26 08:54:38 EDT (Fri, 26 Oct 2012)
@@ -29,7 +29,7 @@
 
 if __name__ == '__main__':
   tuple_min_size=10
-  tuple_max_size=20
+  tuple_max_size=40
   tuple_del_size=10
   boost_root="/home/evansl/prog_dev/boost-svn/ro/boost_1_49_0"
   compiler_map={}
@@ -44,14 +44,19 @@
          , "-std=c++11 -cxx-isystem /home/evansl/download/llvm/svn/llvm/projects/libcxx/include"
          )
   impl_map_hpp={}#implementation key -> implementation include .hpp file.
+  impl_map_hpp["horizontal"]="tuple_impl_horizontal.hpp"
+  impl_map_hpp["vertical"  ]="tuple_impl_vertical.hpp"
+  impl_map_hpp["bcon12_horizontal"]="tuple_impl_bcon12_horizontal.hpp"
+  impl_map_hpp["bcon12_vertical"  ]="tuple_impl_bcon12_vertical.hpp"
+  #impl_map_hpp["std"       ]="tuple_impl_std.hpp"
+  #impl_map_hpp["compstor"  ]="tuple_impl_compstor.hpp"
   impl_map_inc=collections.defaultdict(lambda:"")#implementation key -> -I include flags to compiler
-  #impl_map_hpp["horizontal"]="tuple_impl_horizontal.hpp"
-  #impl_map_hpp["vertical"  ]="tuple_impl_vertical.hpp"
   impl_map_inc["vertical"  ]=\
       " -I"+boost_root\
     #
-  impl_map_hpp["std"       ]="tuple_impl_std.hpp"
-  impl_map_hpp["compstor"  ]="tuple_impl_compstor.hpp"
+  impl_map_inc["bcon12_vertical"  ]=\
+      " -I"+boost_root\
+    #
   impl_map_inc["compstor"  ]=\
       " -I"+boost_root\
     + " -I"+boost_root+"/sandbox/rw/variadic_templates"\
Added: sandbox/variadic_templates/sandbox/slim/test/tuple_impl_bcon12_horizontal.hpp
==============================================================================
--- (empty file)
+++ sandbox/variadic_templates/sandbox/slim/test/tuple_impl_bcon12_horizontal.hpp	2012-10-26 08:54:38 EDT (Fri, 26 Oct 2012)
@@ -0,0 +1,204 @@
+#ifndef TUPLE_IMPL_BCON12_VERTICAL_INCLUDE_HPP
+#define TUPLE_IMPL_BCON12_VERTICAL_INCLUDE_HPP
+//Acknowlegements:
+//  The following code was adapted from part of the code in
+//    https://github.com/ericniebler/home/blob/master/src/tuple/tuple.cpp
+//
+///////////////////////////////////////////////////////////////////////////////
+// tuple.cpp
+//
+// Copyright 2012 Eric Niebler.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <cstdio>
+#include <utility>
+#include <functional>
+#include <type_traits>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+
+#ifndef BRANCHING_FACTOR
+#define BRANCHING_FACTOR 7
+#endif
+
+#ifndef DEPTH
+#define DEPTH 7
+#endif
+
+// C++11 eliminates the need for macros! Oh, wait ...
+#define RETURN(...) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
+
+// New-style enable_if from Matt Calabrese
+#define ENABLE_IF(...) typename std::enable_if<(__VA_ARGS__)>::type *& = detail::enabler
+
+// For adding defaulted default, copy and move constructors, and move/copy assign.
+#define DEFAULTS(CLASS)                                                                             \
+    CLASS() = default; /*required for the type to be trivial!*/                                     \
+    CLASS(CLASS const &) = default; /* memberwise copy */                                           \
+    CLASS(CLASS &&) = default; /* member-wise move */                                               \
+    /* These would otherwise be deleted because we */                                               \
+    /* declared a move constructor! */                                                              \
+    CLASS &operator=(CLASS const &) = default; /* memberwise copy assign */                         \
+    CLASS &operator=(CLASS &&) = default; /* memberwise move assign */                              \
+    /**/
+
+namespace detail
+{
+    extern void* enabler;
+
+    ///////////////////////////////////////////////////////////////////////////
+    // unrefwrap
+    template<typename T>
+    struct unrefwrap
+    {
+        typedef T type;
+    };
+
+    template<typename T>
+    struct unrefwrap<std::reference_wrapper<T> >
+    {
+        typedef T &type;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // as_tuple_element
+    template<typename T>
+    using as_tuple_element = typename unrefwrap<typename std::decay<T>::type>::type;
+
+    ///////////////////////////////////////////////////////////////////////////
+    // ints
+    template<int ...I>
+    struct ints
+    {};
+
+    ///////////////////////////////////////////////////////////////////////////
+    // indices
+    template<int N, typename Ints>
+    struct indices_;
+
+    template<int N, int... I>
+    struct indices_<N, ints<I...>>
+      : indices_<N-1, ints<N-1, I...>>
+    {};
+
+    template<int... I>
+    struct indices_<0, ints<I...>>
+    {
+        typedef ints<I...> type;
+    };
+
+    template<int I>
+    using indices = typename indices_<I, ints<>>::type;
+
+    ///////////////////////////////////////////////////////////////////////////
+    // tuple_elem
+    template<int I, typename T>
+    struct tuple_elem
+    {
+        DEFAULTS(tuple_elem)
+
+        template<typename U
+          , ENABLE_IF(!std::is_same<U, tuple_elem &>::value)>
+        explicit constexpr tuple_elem(U &&u)
+          : value(static_cast<U &&>(u))
+        {}
+
+        typedef T type;
+        T value;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // tuple_impl
+    template<typename Ints, typename ...T>
+    struct tuple_impl;
+
+    template<int... Ints, typename H, typename ...T>
+    struct tuple_impl<ints<0, Ints...>, H, T...>
+        // can't seem to expand two packs in lock step with unrolling. Huh.
+      : tuple_elem<0, H>, tuple_elem<Ints, T>...
+    {
+        DEFAULTS(tuple_impl)
+
+        template<typename U, typename ...V
+          , ENABLE_IF(sizeof...(V) != 0 || !std::is_same<U, tuple_impl &>::value)>
+        explicit constexpr tuple_impl(U &&u, V &&...v) // HACK around gcc bug #53036
+          : tuple_elem<0, H>(static_cast<U &&>(u))
+          , tuple_elem<Ints, T>(static_cast<V &&>(v))...
+        {}
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // get
+    template<int I, typename T>
+    constexpr T &get(tuple_elem<I, T> &t) noexcept
+    {
+        return t.value;
+    }
+
+    template<int I, typename T>
+    constexpr T const &get(tuple_elem<I, T> const &t) noexcept
+    {
+        return t.value;
+    }
+
+    template<int I, typename T>
+    constexpr T &&get(tuple_elem<I, T> &&t) noexcept
+    {
+        return static_cast<T &&>(t.value);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // get_elem
+    template<int I, typename T>
+    tuple_elem<I, T> get_elem(tuple_elem<I, T> const &);
+}
+
+using detail::get;
+
+///////////////////////////////////////////////////////////////////////////////
+// tuple_element
+template<int I, typename Tuple>
+struct tuple_element
+  : decltype(detail::get_elem<I>(std::declval<Tuple>()))
+{};
+
+///////////////////////////////////////////////////////////////////////////////
+// tuple
+template<typename ...T>
+struct tuple_bench;
+
+template<>
+struct tuple_bench<>
+{};
+
+template<typename H, typename ...T>
+struct tuple_bench<H, T...>
+  : detail::tuple_impl<detail::indices<sizeof...(T) + 1>, H, T...>
+{
+    typedef detail::tuple_impl<detail::indices<sizeof...(T) + 1>, H, T...> impl_type;
+
+    DEFAULTS(tuple_bench)
+
+    // not explicit to allow things like: return {42, "allo"};
+    template<typename U, typename ...V
+        , ENABLE_IF(sizeof...(V) == sizeof...(T))
+        , ENABLE_IF(sizeof...(V) != 0 || !std::is_same<U, tuple_bench &>::value)>
+    constexpr tuple_bench(U &&u, V &&...v)
+      : impl_type(static_cast<U &&>(u), static_cast<V &&>(v)...)
+    {}
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// make_tuple
+template<typename ...T>
+tuple_bench<detail::as_tuple_element<T>...> make_tuple(T &&...t)
+{
+    return {t...};
+}
+
+#endif
Added: sandbox/variadic_templates/sandbox/slim/test/tuple_impl_bcon12_vertical.hpp
==============================================================================
--- (empty file)
+++ sandbox/variadic_templates/sandbox/slim/test/tuple_impl_bcon12_vertical.hpp	2012-10-26 08:54:38 EDT (Fri, 26 Oct 2012)
@@ -0,0 +1,196 @@
+#ifndef TUPLE_IMPL_BCON12_VERTICAL_INCLUDE_HPP
+#define TUPLE_IMPL_BCON12_VERTICAL_INCLUDE_HPP
+//Acknowlegements:
+//  The following code was adapted from part of the code in
+//    https://github.com/ericniebler/home/blob/master/src/tuple/unrolled_tuple.hpp
+//
+///////////////////////////////////////////////////////////////////////////////
+// unrolled_tuple.hpp
+//
+// Copyright 2012 Eric Niebler.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <utility>
+#include <functional>
+#include <type_traits>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/iteration/local.hpp>
+#include <boost/preprocessor/arithmetic/dec.hpp>
+#include <boost/preprocessor/comparison/equal.hpp>
+#include <boost/preprocessor/control/expr_if.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+
+// Must be greater than or equal to 1. (1 means don't do loop unrolling.)
+#ifndef UNROLL_MAX
+#define UNROLL_MAX 10
+#endif
+
+// C++11 eliminates the need for macros! Oh, wait ...
+#define RETURN(...) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
+
+// New-style enable_if from Matt Calabrese
+#define ENABLE_IF(...) typename std::enable_if<(__VA_ARGS__)>::type *& = detail::enabler
+
+// For adding defaulted default, copy and move constructors, and move/copy assign.
+#define DEFAULTS(CLASS)                                                                             \
+    CLASS() = default; /*required for the type to be trivial!*/                                     \
+    CLASS(CLASS const &) = default; /* memberwise copy */                                           \
+    CLASS(CLASS &&) = default; /* member-wise move */                                               \
+    /* These would otherwise be deleted because we */                                               \
+    /* declared a move constructor! */                                                              \
+    CLASS &operator=(CLASS const &) = default; /* memberwise copy assign */                         \
+    CLASS &operator=(CLASS &&) = default; /* memberwise move assign */                              \
+    /**/
+
+#define DISABLE_COPY_IF(CLASS, N, T)                                                                \
+    BOOST_PP_COMMA_IF(BOOST_PP_EQUAL(N, 1))                                                         \
+    BOOST_PP_EXPR_IF(                                                                               \
+        BOOST_PP_EQUAL(N, 1)                                                                        \
+      , ENABLE_IF(!std::is_same<T, CLASS &>::value)                                                 \
+    )                                                                                               \
+    /**/
+
+namespace detail
+{
+    extern void* enabler;
+
+    ///////////////////////////////////////////////////////////////////////////
+    template<int I>
+    using int_ = std::integral_constant<int, I>;
+
+    ///////////////////////////////////////////////////////////////////////////
+    // unrefwrap
+    template<typename T>
+    struct unrefwrap
+    {
+        typedef T type;
+    };
+
+    template<typename T>
+    struct unrefwrap<std::reference_wrapper<T> >
+    {
+        typedef T &type;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // as_tuple_element
+    template<typename T>
+    using as_tuple_element = typename unrefwrap<typename std::decay<T>::type>::type;
+}
+
+template<typename ...T>
+struct tuple_bench;
+
+template<>
+struct tuple_bench<>
+{
+};
+
+#define INIT(Z, N, D) t ## N(static_cast< U ## N && >( u ## N ))
+#define MEMBERS(Z, N, D) T ## N t ## N;
+
+#define BOOST_PP_LOCAL_MACRO(N)                                     \
+template<BOOST_PP_ENUM_PARAMS(N, typename T)>                       \
+struct tuple_bench<BOOST_PP_ENUM_PARAMS(N, T)>                            \
+{                                                                   \
+    DEFAULTS(tuple_bench)                                                 \
+                                                                    \
+    template<BOOST_PP_ENUM_PARAMS(N, typename U)                    \
+        DISABLE_COPY_IF(tuple_bench, N, U0)                               \
+    >                                                               \
+    constexpr tuple_bench(BOOST_PP_ENUM_BINARY_PARAMS(N, U, &&u))         \
+      : BOOST_PP_ENUM(N, INIT, ~)                                   \
+    {}                                                              \
+                                                                    \
+    BOOST_PP_REPEAT(N, MEMBERS, ~)                                  \
+};                                                                  \
+/**/
+
+#define BOOST_PP_LOCAL_LIMITS (1, UNROLL_MAX)
+#include BOOST_PP_LOCAL_ITERATE()
+
+// A tuple type that can be statically initialized
+template<BOOST_PP_ENUM_PARAMS(UNROLL_MAX, typename T), typename ...Tail>
+struct tuple_bench<BOOST_PP_ENUM_PARAMS(UNROLL_MAX, T), Tail...>
+{
+    DEFAULTS(tuple_bench)
+
+    // Not explicit to allow things like: return {42, "allo"};.
+    template<BOOST_PP_ENUM_PARAMS(UNROLL_MAX, typename U), typename ...Rest
+      , ENABLE_IF(sizeof...(Rest)==sizeof...(Tail))
+        DISABLE_COPY_IF(tuple_bench, UNROLL_MAX, U0)
+    >
+    constexpr tuple_bench(BOOST_PP_ENUM_BINARY_PARAMS(UNROLL_MAX, U, &&u), Rest &&...rest)
+      : BOOST_PP_ENUM(UNROLL_MAX, INIT, ~)
+      , tail(static_cast<Rest &&>(rest)...) // std::forward is NOT constexpr!
+    {}
+
+    BOOST_PP_REPEAT(UNROLL_MAX, MEMBERS, ~)
+    tuple_bench<Tail...> tail;
+};
+
+#undef INIT
+#undef MEMBERS
+#undef DEFAULTS
+
+namespace detail
+{
+    // Work-around strange gcc bug
+    template<int J>
+    struct impl
+    {
+        #define BOOST_PP_LOCAL_MACRO(N)                                                             \
+        template<typename Tuple>                                                                    \
+        static inline constexpr auto get_elem(Tuple &&that, int_<N>)                                \
+        RETURN(                                                                                     \
+            (static_cast<Tuple &&>(that).BOOST_PP_CAT(t, N))  /*extra parens are significant!*/     \
+        )                                                                                           \
+        /**/
+
+        #define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC(UNROLL_MAX))
+        #include BOOST_PP_LOCAL_ITERATE()
+
+        template<typename Tuple, int I>
+        static inline constexpr auto get_elem(Tuple &&that, int_<I>)
+        RETURN(
+            impl<I-I>::get_elem(static_cast<Tuple &&>(that).tail, int_<I-UNROLL_MAX>())
+        )
+    };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// get
+template<int I, typename ...T>
+inline constexpr auto get(tuple_bench<T...> &tup)
+RETURN(
+    detail::impl<I-I>::get_elem(tup, detail::int_<I>())
+)
+
+template<int I, typename ...T>
+inline constexpr auto get(tuple_bench<T...> const &tup)
+RETURN(
+    detail::impl<I-I>::get_elem(tup, detail::int_<I>())
+)
+
+template<int I, typename ...T>
+inline constexpr auto get(tuple_bench<T...> &&tup)
+RETURN(
+    detail::impl<I-I>::get_elem(static_cast<tuple_bench<T...> &&>(tup), detail::int_<I>())
+)
+
+///////////////////////////////////////////////////////////////////////////////
+// make_tuple
+template<typename ...T>
+inline tuple_bench<detail::as_tuple_element<T>...> make_tuple(T &&...t)
+{
+    return {t...};
+}
+
+#endif