diff --git a/doc/reference/c++/utilities/tupletools.rst b/doc/reference/c++/utilities/tupletools.rst index d86a376e..3a76f78f 100644 --- a/doc/reference/c++/utilities/tupletools.rst +++ b/doc/reference/c++/utilities/tupletools.rst @@ -2,17 +2,16 @@ .. _util_tuple: -Tuple compile time tools +Tuple tools ============================= -Very useful for lib developers, they fill a missing gap in the std library. -They implement various standard functional operations, at compile time, -on tuple... +Various standard functional operations on tuple (which should be in the STL but are not ...). -.. note:: - - Simple measures have shown that these routines are **as fast as native code** (tested on gcc, clang, icc), - due to inlining. They can therefore be used in critical parts of codes. +.. + .. note:: + + Simple measures have shown that these routines are **as fast as native code** (tested on gcc, clang, icc), + due to inlining. They can therefore be used in critical parts of codes. apply ----------------------------------------------- @@ -21,15 +20,21 @@ apply Given a function object `f`, and its arguments stored in a tuple `t`, and we want to apply `f` on `t`. - Python equivalent : `f(*t)` +*Python equivalent*: + + .. code-block:: python + + def apply(f,t) : + return f(*t) *Synopsis* :: template auto apply (Function && f, Tuple const & t); - -*Solution* : + +*Example* : .. triqs_example:: ./tupletools_0.cpp + for_each ------------------------------------------------------------------------- @@ -38,12 +43,204 @@ for_each Given a function object `f`, we want to apply it to all elements of a tuple `t`. - Python equivalent : `for x in t : f(x)` +*Python equivalent*: + + .. code-block:: python + + def for_each(t,f) : + for x in t: + f(x) *Synopsis* :: template void for_each(Tuple const & t, Function && f); -*Solution* : +*Example* : .. triqs_example:: ./tupletools_1.cpp + +for_each_zip +------------------------------------------------------------------------- + +*Purpose* : `apply a function for each element of tuple zip (in order)` + + +*Python equivalent*: + + .. code-block:: python + + def for_each(f,t0,t1) : + for x0,x1 in itertools.zip(t0,t1): + f(x0,x1) + +*Synopsis* :: + + template void for_each_zip(F &&f, T0 &&t0, T1 &&t1); + template void for_each_zip(F &&f, T0 &&t0, T1 &&t1, T2 &&t2); + +*Example* : + +.. triqs_example:: ./tupletools_2.cpp + +map +------------------------------------------------------------------------- + +*Purpose* : `map a function on a tuple to create a new tuple` + +*Python equivalent*: + + .. code-block:: python + + def map(f,t) : + return (f(x) for x in t) + +*Synopsis* :: + + template auto map(F &&f, T &&t); + +*Returns*: + + The result is a tuple, of the same length as T, made of the evaluation of f on the elements on T + +*Example* : + +.. triqs_example:: ./tupletools_3.cpp + +fold +------------------------------------------------------------------------- + +*Purpose* : `reduction of a tuple with a function` + +*Python equivalent*: + + .. code-block:: python + + def fold(f,t,r) : + return reduce(f,t,r) + +*Synopsis* :: + + (1) template + decltype(auto) fold(F &&f, T &&t, R &&r); + + (2) template + decltype(auto) fold(F &&f, T0 &&t0, T1 &&t1, R &&r); + +*Returns*:: + + f(get(t), + f(get(t), + ..., + f(get<0>(t),r))) (1) + + f(get(t0), get(t1), + f(get(t0), get(t1), + ..., + f(get<0>(t0), get<0>(t1), r))) (2) + +*Parameters* : + + * f : a callable object of signature :: + + f(x, r) -> r' (1) + f(x, y, r) -> r' (2) + + The return type of f must be a valid last parameter for f (at least for one overload). + + * t : a tuple + + * t0,t1 : two tuples of the same size + + * r : anything that can be a last parameter for f. + + * Precondition: everything so that the resulting expression is valid (in particular, f must be called on each tuple elements, + with its return type as last parameter. + +.. warning:: + + The type of the result is not necessarly R : it is automatically deduced from this expression. Cf example. + + +*Example* : + +.. triqs_example:: ./tupletools_4.cpp + +reverse +------------------------------------------------------------------------- + +*Purpose* : `lazy reverse of a tuple` + +*Python equivalent*: None. + +*Synopsis* :: + + namespace std { + template TU reverse(std::tuple && x); + template TU reverse(std::tuple & x); + template TU reverse(std::tuple const& x); + } + +.. warning:: + + reverse is declared in std:: to benefit from ADL (a bit dangerous, but ok here). + +*Returns*: + + TU is a tuple like type, that : + + * Contains a ref of the original tuple, or the tuple if a && was passed. + * Hence, no copy is ever made. + * Accepts std::get and std::tuple_size, like tuple. + + reverse(t) can therefore be used in place of a regular tuple in the algorithms of this section. + +*Example* : + +.. triqs_example:: ./tupletools_reverse.cpp + +called_on_tuple +------------------------------------------------------------------------- + +*Purpose* : `Adapting a function to call with a tuple argument and flatten it` + +*Python equivalent*: + + .. code-block:: python + + def called_on_tuple(f) : + return lambda x : f(*x) + +*Synopsis* :: + + template F2 called_on_tuple(F &&f); + +*Returns*: + + F2 is a function object which adapts the function f for calling on a tuple. + + The following call are therefore equivalent:: + + called_on_tuple(f)( std::tie(x0,x1,x2)) + + f(x0,x1,x2) + +*Example* : + +.. triqs_example:: ./tupletools_called.cpp + + +*Implementation* : + + The C++ is simple in fact :: + + template struct _called_on_tuple { + F _f; + template decltype(auto) operator()(Tu &&tu) { + return apply(_f, std::forward(tu)); + } + }; + + template _called_on_tuple called_on_tuple(F &&f) { + return {std::forward(f)}; + } + diff --git a/doc/reference/c++/utilities/tupletools_0.cpp b/doc/reference/c++/utilities/tupletools_0.cpp index de1c4d07..0bfa4c45 100644 --- a/doc/reference/c++/utilities/tupletools_0.cpp +++ b/doc/reference/c++/utilities/tupletools_0.cpp @@ -1,11 +1,11 @@ #include #include int main() { - auto fun = [](int i, double x, double y, int k) { return 6 * k + i - 1.3 * x + 2 * y; }; auto t = std::make_tuple(1, 2.3, 4.3, 8); auto res = triqs::tuple::apply(fun, t); + std::cout << " f(t) =" << res << std::endl; } diff --git a/doc/reference/c++/utilities/tupletools_1.cpp b/doc/reference/c++/utilities/tupletools_1.cpp index fe3eb2bb..b7dfb08f 100644 --- a/doc/reference/c++/utilities/tupletools_1.cpp +++ b/doc/reference/c++/utilities/tupletools_1.cpp @@ -1,15 +1,10 @@ #include #include -struct print_t { - template void operator()(T x) { std::cout << x << " "; } -}; - int main() { - auto t = std::make_tuple(1, 2.3, 4.3, 8, "hello"); - triqs::tuple::for_each(t, print_t()); + auto t = std::make_tuple(1, 2.3, 4.3, 8); + auto l = [](double x) { std::cout << x << " "; }; - // C++14 solution : with generic lambda, there is no need to define a print_t ... - // triqs::tuple::for_each(t, [](auto x) { std::cout< +#include + +int main() { + auto t1 = std::make_tuple(1, 2.3, 4.3, 8); + auto t2 = std::make_tuple('|','|','|','|'); + auto l = [](double x, char c) { std::cout << c << " " << x << " "; }; + + triqs::tuple::for_each_zip(l, t1, t2); +} + diff --git a/doc/reference/c++/utilities/tupletools_3.cpp b/doc/reference/c++/utilities/tupletools_3.cpp new file mode 100644 index 00000000..0e649e14 --- /dev/null +++ b/doc/reference/c++/utilities/tupletools_3.cpp @@ -0,0 +1,12 @@ +#include +#include + +int main() { + auto t = std::make_tuple(1, 2.3, 4.3, 8); + auto l = [](double x) { return -x; }; + + auto res = triqs::tuple::map(l, t); + + std::cout << res << std::endl; +} + diff --git a/doc/reference/c++/utilities/tupletools_4.cpp b/doc/reference/c++/utilities/tupletools_4.cpp new file mode 100644 index 00000000..e6807315 --- /dev/null +++ b/doc/reference/c++/utilities/tupletools_4.cpp @@ -0,0 +1,24 @@ +#include +#include + +int main() { + auto t = std::make_tuple(1, 2.3, 4.3, 8); + + // a simple example : make a sum + auto f = [](double x, double r) { return x + r; }; + auto res = triqs::tuple::fold(f, t, 0); // <-- R is int but res is a double (from f's return type). + + std::cout << res << std::endl; + + // the types of x and r may be different + triqs::tuple::fold([](double x, std::ostream & os)->std::ostream & { return os << "|" << x; }, t, std::cout); + + // example with zip + auto t0 = std::make_tuple(1, 2, 3, 4); + auto t1 = std::make_tuple(1, -1, 1, -1); + + auto res2 = triqs::tuple::fold([](double x, double y, double r) { return y * x + r; }, t0, t1, 0); + + std::cout << "\n " << res2 << std::endl; +} + diff --git a/doc/reference/c++/utilities/tupletools_called.cpp b/doc/reference/c++/utilities/tupletools_called.cpp new file mode 100644 index 00000000..83e0f0bb --- /dev/null +++ b/doc/reference/c++/utilities/tupletools_called.cpp @@ -0,0 +1,11 @@ +#include +#include +int main() { + auto fun = [](int i, double x, double y, int k) { return 6 * k + i - 1.3 * x + 2 * y; }; + auto t = std::make_tuple(1, 2.3, 4.3, 8); + + auto res = triqs::tuple::called_on_tuple(fun)(t); + + std::cout << " f(t) =" << res << std::endl; +} + diff --git a/doc/reference/c++/utilities/tupletools_reverse.cpp b/doc/reference/c++/utilities/tupletools_reverse.cpp new file mode 100644 index 00000000..759392da --- /dev/null +++ b/doc/reference/c++/utilities/tupletools_reverse.cpp @@ -0,0 +1,11 @@ +#include +#include + +int main() { + auto t = std::make_tuple(1, 2.3, 4.3, 8); + auto l = [](double x) { std::cout << x << " "; }; + + triqs::tuple::for_each(t, l); + std::cout << std::endl; + triqs::tuple::for_each(reverse(t), l); +} diff --git a/test/triqs/gfs/curry1.cpp b/test/triqs/gfs/curry1.cpp index 054ae21d..da937a15 100644 --- a/test/triqs/gfs/curry1.cpp +++ b/test/triqs/gfs/curry1.cpp @@ -37,6 +37,9 @@ try { auto G_w_wn_view = G_w_wn(); auto G_w_wn_sl0_a = partial_eval<0>(G_w_wn(), 8); + + //decltype(G_w_wn_sl0_a.mesh())::zozo(); + static_assert(std::is_same::type, const gf_mesh>::value, "oops"); //auto G_w_wn_curry0_a = curry0(G_w_wn); //auto G_w_wn_sl0_a = slice_mesh0(G_w_wn(), 8); diff --git a/test/triqs/utility/tuple_tools.cpp b/test/triqs/utility/tuple_tools.cpp index 70b9360f..41408e07 100644 --- a/test/triqs/utility/tuple_tools.cpp +++ b/test/triqs/utility/tuple_tools.cpp @@ -19,7 +19,6 @@ * ******************************************************************************/ #include -#include #include #include #include @@ -30,10 +29,6 @@ struct fun { double operator()(int i, double x, double y, int k) { return 6*k + i - 1.3*x + 2*y;} }; -struct fun2 { - double operator()(double x, double y) { return x+y;} -}; - struct print_t { template void operator()(T x) { std::cerr << x << " "; } @@ -74,12 +69,8 @@ int main(int argc, char **argv) { } { - auto r = triqs::tuple::apply_on_zip(fun2(),t1,t2); - std::cerr << " [f(a,b) for (a,b) in zip(t1,t2)] =" - << std::get<0>(r) << " " - << std::get<1>(r) << " " - << std::get<2>(r) << " " - << std::get<3>(r) << std::endl; + auto r = triqs::tuple::map_on_zip_v2([](double x, double y) { return x + y; }, t1, t2); + std::cerr << " [f(a,b) for (a,b) in zip(t1,t2)] =" << r << std::endl; } std::cerr << " ----- fold ----"<< std::endl ; @@ -103,7 +94,7 @@ int main(int argc, char **argv) { } { - auto res = triqs::tuple::fold_on_zip([](double x, double y, double r) { return x+ 2*y +r;}, t1,t2, 0); + auto res = triqs::tuple::fold([](double x, double y, double r) { return x+ 2*y +r;}, t1,t2,0); std::cerr << " " << res << std::endl ; if ( std::abs((res - 35.6)) > 1.e-13) throw std::runtime_error(" "); } @@ -161,9 +152,6 @@ int main(int argc, char **argv) { auto t2= std::make_tuple(0,1); std::cout << "filter out "<< t2 << triqs::tuple::filter_out<0>(t2)<< std::endl; - - typedef typename triqs::tuple::filter_t_tr< decltype(t), 0,2,3>::type TY; - static_assert(std::is_same(t))>::value, "EEE"); } { // filter diff --git a/triqs/gfs/meshes/product.c11.hpp b/triqs/gfs/meshes/product.c11.hpp index 8b888e93..519dd8fe 100644 --- a/triqs/gfs/meshes/product.c11.hpp +++ b/triqs/gfs/meshes/product.c11.hpp @@ -63,7 +63,7 @@ namespace gfs { /// Conversions point <-> index <-> linear_index typename domain_t::point_t index_to_point(index_t const &ind) const { domain_pt_t res; - triqs::tuple::apply_on_zip(_aux1(), res, m_tuple, ind); + triqs::tuple::map_on_zip(_aux1(), res, m_tuple, ind); return res; } @@ -77,10 +77,8 @@ namespace gfs { public: /// Flattening index to linear : index[0] + component[0].size * (index[1] + component[1].size* (index[2] + ....)) size_t index_to_linear(index_t const &ii) const { - return triqs::tuple::fold_on_zip(_aux2(), reverse(m_tuple), reverse(ii), size_t(0)); + return triqs::tuple::fold(_aux2(), reverse(m_tuple), reverse(ii), size_t(0)); } - // size_t index_to_linear(index_t const & ii) const { return triqs::tuple::fold_on_zip([](auto const &m, auto const &i, auto R) - //{return m.index_to_linear(i) + R * m.size();} , m_tuple, ii, size_t(0)); } private: struct _aux3 { @@ -92,7 +90,7 @@ namespace gfs { public: /// Flattening index to linear : index[0] + component[0].size * (index[1] + component[1].size* (index[2] + ....)) size_t mp_to_linear(m_pt_tuple_t const &mp) const { - return triqs::tuple::fold_on_zip(_aux3(), reverse(m_tuple), reverse(mp), size_t(0)); + return triqs::tuple::fold(_aux3(), reverse(m_tuple), reverse(mp), size_t(0)); } // @@ -134,8 +132,8 @@ namespace gfs { public: mesh_point_t() = default; mesh_point_t(mesh_product const &m_, index_t index_) - : m(&m_), _c(triqs::tuple::apply_on_zip(F2(), m_.m_tuple, index_)), _atend(false) {} - mesh_point_t(mesh_product const &m_) : m(&m_), _c(triqs::tuple::apply_on_tuple(F1(), m_.m_tuple)), _atend(false) {} + : m(&m_), _c(triqs::tuple::map_on_zip(F2(), m_.m_tuple, index_)), _atend(false) {} + mesh_point_t(mesh_product const &m_) : m(&m_), _c(triqs::tuple::map(F1(), m_.m_tuple)), _atend(false) {} m_pt_tuple_t const &components_tuple() const { return _c; } size_t linear_index() const { return m->mp_to_linear(_c); } const mesh_product *mesh() const { return m; } diff --git a/triqs/gfs/meshes/product.c14.hpp b/triqs/gfs/meshes/product.c14.hpp index 76f74968..c8200337 100644 --- a/triqs/gfs/meshes/product.c14.hpp +++ b/triqs/gfs/meshes/product.c14.hpp @@ -53,25 +53,25 @@ namespace gfs { typename domain_t::point_t index_to_point(index_t const &ind) const { domain_pt_t res; auto l = [](auto &p, auto const &m, auto const &i) { p = m.index_to_point(i); }; - triqs::tuple::apply_on_zip(l, res, m_tuple, ind); + triqs::tuple::map_on_zip(l, res, m_tuple, ind); return res; } /// Flattening index to linear : index[0] + component[0].size * (index[1] + component[1].size* (index[2] + ....)) size_t index_to_linear(index_t const &ii) const { auto l = [](auto const &m, auto const &i, size_t R) { return m.index_to_linear(i) + R * m.size(); }; - return triqs::tuple::fold_on_zip(l,reverse(m_tuple), reverse(ii), size_t(0)); + return triqs::tuple::fold(l, reverse(m_tuple), reverse(ii), size_t(0)); } /// Flattening index to linear : index[0] + component[0].size * (index[1] + component[1].size* (index[2] + ....)) size_t mp_to_linear(m_pt_tuple_t const &mp) const { auto l = [](auto const &m, auto const &p, size_t R) { return p.linear_index() + R * m.size(); }; - return triqs::tuple::fold_on_zip(l, reverse(m_tuple), reverse(mp), size_t(0)); + return triqs::tuple::fold(l, reverse(m_tuple), reverse(mp), size_t(0)); } utility::mini_vector shape() const { utility::mini_vector res; - auto l = [&res](auto const &m, int i) mutable { res[i] = m.size(); }; + auto l = [&res](int i, auto const &m) mutable { res[i] = m.size(); }; triqs::tuple::for_each_enumerate(m_tuple, l); return res; } @@ -97,9 +97,9 @@ namespace gfs { mesh_point_t() = default; mesh_point_t(mesh_product const &m_, index_t index_) : m(&m_) - , _c(triqs::tuple::apply_on_zip([](auto const & m, auto const & i) { return m[i]; }, m_.m_tuple, index_)) + , _c(triqs::tuple::map_on_zip([](auto const & m, auto const & i) { return m[i]; }, m_.m_tuple, index_)) , _atend(false) {} - mesh_point_t(mesh_product const &m_) : m(&m_), _c(triqs::tuple::apply_on_tuple(F1(), m_.m_tuple)), _atend(false) {} + mesh_point_t(mesh_product const &m_) : m(&m_), _c(triqs::tuple::map(F1(), m_.m_tuple)), _atend(false) {} m_pt_tuple_t const &components_tuple() const { return _c; } size_t linear_index() const { return m->mp_to_linear(_c); } const mesh_product *mesh() const { return m; } @@ -145,21 +145,21 @@ namespace gfs { /// Write into HDF5 friend void h5_write(h5::group fg, std::string subgroup_name, mesh_product const &m) { h5::group gr = fg.create_group(subgroup_name); - auto l = [gr](auto const &m, int N) { h5_write(gr, "MeshComponent" + std::to_string(N), m); }; + auto l = [gr](int N, auto const &m) { h5_write(gr, "MeshComponent" + std::to_string(N), m); }; triqs::tuple::for_each_enumerate(m.components(), l); } /// Read from HDF5 friend void h5_read(h5::group fg, std::string subgroup_name, mesh_product &m) { h5::group gr = fg.open_group(subgroup_name); - auto l = [gr](auto &m, int N) { h5_read(gr, "MeshComponent" + std::to_string(N), m); }; + auto l = [gr](int N, auto &m) { h5_read(gr, "MeshComponent" + std::to_string(N), m); }; triqs::tuple::for_each_enumerate(m.components(), l); } /// BOOST Serialization friend class boost::serialization::access; template void serialize(Archive &ar, const unsigned int version) { - auto l = [&ar](auto &m, int N) { ar &TRIQS_MAKE_NVP("MeshComponent" + std::to_string(N), m); }; + auto l = [&ar](int N, auto &m) { ar &TRIQS_MAKE_NVP("MeshComponent" + std::to_string(N), m); }; triqs::tuple::for_each_enumerate(m_tuple, l); } diff --git a/triqs/gfs/product.hpp b/triqs/gfs/product.hpp index d08d7d46..51a8f559 100644 --- a/triqs/gfs/product.hpp +++ b/triqs/gfs/product.hpp @@ -164,7 +164,7 @@ namespace gfs { { static constexpr int R = sizeof...(Args); // build the evaluators, as a tuple of ( evaluator ( mesh_component, args)) - triqs::tuple::call_on_zip(_poly_lambda(), evals, g->mesh().components(), std::make_tuple(args...)); + triqs::tuple::for_each_zip(_poly_lambda(), evals, g->mesh().components(), std::make_tuple(args...)); return std::get(evals)(make_binder(g, std::make_tuple(), evals)); } }; diff --git a/triqs/utility/c14.hpp b/triqs/utility/c14.hpp index c9165cf9..6d5480b0 100644 --- a/triqs/utility/c14.hpp +++ b/triqs/utility/c14.hpp @@ -26,6 +26,33 @@ // backward compat. C++11 compilers. // new stuff in +// C++14 detection in gcc (4.9 like recent clang). +#if __cplusplus > 201103L + +#ifndef __cpp_generic_lambdas +#define __cpp_generic_lambdas +#endif + +#ifndef __cpp_decltype_auto +#define __cpp_decltype_auto +#endif + +#ifndef __cpp_return_type_deduction +#define __cpp_return_type_deduction +#endif + +#endif + +// C++11 workaround +#if not defined(__cpp_return_type_deduction) or not defined(__cpp_decltype_auto) +#define TRIQS_C11 +#define AUTO_DECL auto +#define RETURN(X,...) ->decltype(X) { __VA_ARGS__; return X;} +#else +#define AUTO_DECL decltype(auto) +#define RETURN(X,...) { __VA_ARGS__; return X;} +#endif + namespace std { namespace c14 { @@ -130,3 +157,6 @@ namespace std { namespace std14 { using namespace std::c14; } + + + diff --git a/triqs/utility/tuple_tools.hpp b/triqs/utility/tuple_tools.hpp index 732c6e53..4ce8061f 100644 --- a/triqs/utility/tuple_tools.hpp +++ b/triqs/utility/tuple_tools.hpp @@ -2,7 +2,7 @@ * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * - * Copyright (C) 2013 by O. Parcollet + * Copyright (C) 2012-2014 by O. Parcollet * * TRIQS is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software @@ -18,331 +18,379 @@ * TRIQS. If not, see . * ******************************************************************************/ -#ifndef TRIQS_UTILITY_TUPLE_TOOLS_H -#define TRIQS_UTILITY_TUPLE_TOOLS_H +#pragma once #include -#include #include "./c14.hpp" -#include +#include +#include // adding to the std lib the reversed lazy tuple... // overloading & specializing only the functions needed here. namespace std { + + // Reverse template struct _triqs_reversed_tuple {TU _x;}; template _triqs_reversed_tuple> reverse(std::tuple && x) { return {move(x)};} template _triqs_reversed_tuple&> reverse(std::tuple & x) { return {x};} template _triqs_reversed_tupleconst &> reverse(std::tuple const & x) { return {x};} - template auto get(_triqs_reversed_tuple const & t) - DECL_AND_RETURN(std::get>::value-1-pos>(t._x)); - - template auto get(_triqs_reversed_tuple & t) - DECL_AND_RETURN(std::get>::value-1-pos>(t._x)); - - template auto get(_triqs_reversed_tuple && t) - DECL_AND_RETURN(std::get>::value-1-pos>(move(t)._x)); + template AUTO_DECL get(_triqs_reversed_tuple const & t) + RETURN(std::get>::value-1-pos>(t._x)); + + template AUTO_DECL get(_triqs_reversed_tuple & t) + RETURN(std::get>::value-1-pos>(t._x)); + + template AUTO_DECL get(_triqs_reversed_tuple && t) + RETURN(std::get>::value-1-pos>(move(t)._x)); + + template class tuple_size<_triqs_reversed_tuple> : public tuple_size> {}; + + // Zipped tuple: + template struct _triqs_zipped_tuple { + std::tuple _tu; + template _triqs_zipped_tuple(U &&... u) : _tu(std::forward(u)...) {} + + template auto _get(std::c14::index_sequence) RETURN(std::tie(std::get(std::get(_tu))...)); + template auto _get(std::c14::index_sequence) const RETURN(std::tie(std::get(std::get(_tu))...)); + }; + + template + AUTO_DECL get(_triqs_zipped_tuple const &tu) RETURN(tu.template _get(std14::make_index_sequence())); + + template struct tuple_size<_triqs_zipped_tuple> : public std::tuple_size> {}; + + template _triqs_zipped_tuple zip(T &&... x) { + return {std::forward(x)...}; + } - template class tuple_size<_triqs_reversed_tuple> : public tuple_size>{}; } - namespace triqs { namespace tuple { + /// _get_seq() : from a tuple T, return the index sequence of the tuple length + template std14::make_index_sequence>::value> _get_seq() { + return {}; + } + + /// _get_seq_len : constexpr : return the length of the tuple + template constexpr int _get_seq_len() { return std::tuple_size>::value; } + + /// basic tools + template struct _int {}; + template struct all_indices : _int... {}; + + // --- impl complement ----- + template struct complement_sequence_impl { + static complement_sequence_impl get(_int) {} + static complement_sequence_impl get(...) {} + using type = typename decltype(get(hole_seq()))::type; + }; + + template struct complement_sequence_impl<-1, hole_seq, Is...> { + using type = std14::index_sequence; + }; + + /// An index sequence of elements of [0,N-1] which are NOT Is + template using complement_sequence = typename complement_sequence_impl>::type; + + /** + * apply(f, t) + * f : a callable object + * t a tuple + * Returns : f(t0, t1 ...) + * Cf : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3915.pdf + * for the idea of using the sequence, which is used several times below. + */ + template + AUTO_DECL apply_impl(F &&f, T &&t, std14::index_sequence) RETURN(f(std::get(std::forward(t))...)); + + template + AUTO_DECL apply(F &&f, T &&t) RETURN(apply_impl(std::forward(f), std::forward(t), _get_seq())); + + /** + * apply_construct(t) + * C : a class + * t a tuple + * Returns : C{t0, t1, ....} + */ + template + AUTO_DECL apply_construct_impl(T &&t, std14::index_sequence) RETURN(C{std::get(std::forward(t))...}); + + template + AUTO_DECL apply_construct(T &&t) RETURN(apply_construct_impl(std::forward(t), _get_seq())); + + /** + * called_on_tuple(f) + * f : a callable object + * Wrapping a function to make it callable from a tuple + * called_on_tuple(f)( std::tie(x0,x1,x2)) is equivalent to f(x0,x1,x2) + */ + template struct _called_on_tuple { + F _f; + template AUTO_DECL operator()(Tu &&tu) RETURN(apply(_f, std::forward(tu))); + }; + + template _called_on_tuple called_on_tuple(F &&f) { + return {std::forward(f)}; + } + + // Implementation tools + // _for_each_impl (f, x0, x1, ..., xn) calls f(x0); f(x1); ... f(xn); IN THIS ORDER + template void _for_each_impl(F &&f) {} + + template void _for_each_impl(F &&f, T0 &&x0, T &&... x) { + f(std::forward(x0)); + _for_each_impl(f, std::forward(x)...); + } + + // _for_each_apply_impl (f, t0, t1, ..., tn) calls apply(f,x0); apply(f,t1); ... apply(f,tn); + template void _for_each_apply_impl(F &&f) {} + + template void _for_each_apply_impl(F &&f, T0 &&t0, T &&... t) { + apply(f, std::forward(t0)); + _for_each_apply_impl(f, std::forward(t)...); + } + + /** + * for_each(t, f) + * t: a tuple + * f: a callable object + * calls f on all tuple elements in the order of the tuple: f(x) for all x in t + */ + template void for_each_impl(F &&f, T &&t, std14::index_sequence) { + _for_each_impl(f, std::get(t)...); + } + + template void for_each(T &&t, F &&f) { for_each_impl(f, std::forward(t), _get_seq()); } + + /* for_each_enumerate(t, f) + * t: a tuple + * f: a callable object + * calls f on all tuple elements: + * Python equivalent : + * for n,x in enumrate(t): f(n,x) + */ + template void _for_each_enum_impl(F &&f, T &&t, std14::index_sequence) { + _for_each_apply_impl(f, std::tuple(t))>(Is, std::get(t))...); + // not make_tuple here, we keep the ref given by the get + } + + template void for_each_enumerate(T &&t, F &&f) { + _for_each_enum_impl(f, std::forward(t), _get_seq()); + } + + /** + * for_each_zip(f, t1,t2) + * f : a callable object + * t1,t2 : two tuples + * calls f on all tuple elements: f(x1,x2) for x1 in t1 for x2 in t2 + */ + template + void _for_each_zip_impl(std14::index_sequence, F &&f, T0 &&t0, T1 &&t1) { + _for_each_impl(called_on_tuple(std::forward(f)), std::tie(std::get(t0), std::get(t1))...); + } + + template void for_each_zip(F &&f, T0 &&t0, T1 &&t1) { + _for_each_zip_impl(_get_seq(), std::forward(f), std::forward(t0), std::forward(t1)); + } + + /** + * for_each_zip(f, t1,t2,t3) + * f : a callable object + * t1,t2,t3 : three tuples + * calls f on all tuple elements: f(x1,x2,x3) for x1 in t1 for x2 in t2 for x3 in t3 + */ + template + void _for_each_zip_impl(std14::index_sequence, F &&f, T0 &&t0, T1 &&t1, T2 &&t2) { + _for_each_impl(called_on_tuple(std::forward(f)), std::tie(std::get(t0), std::get(t1), std::get(t2))...); + } + + template void for_each_zip(F &&f, T0 &&t0, T1 &&t1, T2 &&t2) { + _for_each_zip_impl(_get_seq(), std::forward(f), std::forward(t0), std::forward(t1), std::forward(t2)); + } + + /** + * map(f, t) + * f : a callable object + * t tuple + * Returns : [f(i) for i in t] + */ + template + AUTO_DECL _map_impl(F &&f, T &&t, std14::index_sequence) + RETURN(std::make_tuple(std::forward(f)(std::get(t))...)); + + template + AUTO_DECL map(F &&f, T &&t) RETURN(_map_impl(std::forward(f), std::forward(t), _get_seq())); + + /** + * map_on_zip(f, t1, t2) + * f : a callable object + * t1, t2 two tuples of the same size + * Returns : [f(i,j) for i,j in zip(t1,t2)] + */ + template + auto _map_impl(F &&f, T0 &&t0, T1 &&t1, std14::index_sequence) + RETURN(std::make_tuple(std::forward(f)(std::get(t0), std::get(t1))...)); + + template + auto map_on_zip(F &&f, T0 &&t0, T1 &&t1) + RETURN(_map_impl(std::forward(f), std::forward(t0), std::forward(t1), _get_seq())); + + template + auto map_on_zip_v2(F &&f, T0 &&t0, T1 &&t1) + RETURN(map(called_on_tuple(f), zip(t0,t1))); + + /** + * map_on_zip(f,t0,t1,t2) + * f : a callable object + * t0, t1, t2 two tuples of the same size + * Returns : [f(i,j,k) for i,j,k in zip(t0,t1,t2)] + */ + template + auto _map_impl(F &&f, T0 &&t0, T1 &&t1, T2 &&t2, std14::index_sequence) + RETURN(std::make_tuple(std::forward(f)(std::get(t0), std::get(t1), std::get(t2))...)); + + template + auto map_on_zip(F &&f, T0 &&t0, T1 &&t1, T2 &&t2) + RETURN(_map_impl(std::forward(f), std::forward(t0), std::forward(t1), std::forward(t2), _get_seq())); + +/** + * fold(f, t1, r_init) + * f : a callable object : f(x,r) -> r' + * t a tuple + * Returns : f(xN,f(x_N-1,...f(x0,r_init)) on the tuple + */ +#ifndef TRIQS_C11 + template decltype(auto) fold_impl(_int, F &&f, T &&t, R &&r) { + return fold_impl(_int(), std::forward(f), std::forward(t), + f(std::get<_get_seq_len() - 1 - pos>(t), std::forward(r))); + } + template R fold_impl(_int<-1>, F &&f, T &&t, R &&r) { return std::forward(r); } + + template decltype(auto) fold(F &&f, T &&t, R &&r) { + return fold_impl(_int<_get_seq_len() - 1>(), std::forward(f), std::forward(t), std::forward(r)); + } +#else + // old implementation, not modified for C++11 + + template struct fold_impl { + template + auto operator()(F &&f, T &&t, + R &&r)DECL_AND_RETURN(fold_impl()(std::forward(f), std::forward(t), + f(std::get(t), std::forward(r)))); + }; + + template struct fold_impl { + template R operator()(F &&f, T &&t, R &&r) { return std::forward(r); } + }; + + template + auto fold(F &&f, T &&t, R &&r) + DECL_AND_RETURN(fold_impl>::value, std::tuple_size>::value - 1, + T>()(std::forward(f), std::forward(t), std::forward(r))); + +#endif + + /** + * fold(f, r_init, t1, t2) + * f : a callable object + * t1, t2 two tuples of the same size + * Returns : f(x0,y0,f(x1,y1,,f(....)) for t1 = (x0,x1 ...) and t2 = (y0,y1...). + */ + +#ifndef TRIQS_C11 + template + decltype(auto) fold_impl(_int, F &&f, T0 &&t0, T1 &&t1, R &&r) { + constexpr int n = _get_seq_len() - 1 - pos; + return fold_impl(_int(), std::forward(f), std::forward(t0), std::forward(t1), + f(std::get(t0), std::get(t1), std::forward(r))); + } + + template R fold_impl(_int<-1>, F &&f, T0 &&t0, T1 &&t1, R &&r) { + return std::forward(r); + } + + template decltype(auto) fold(F &&f, T0 &&t0, T1 &&t1, R &&r) { + return fold_impl(_int<_get_seq_len() - 1>(), std::forward(f), std::forward(t0), std::forward(t1), + std::forward(r)); + } +#else +// old implementation, not modified for C++11 + + template struct fold_on_zip_impl { + template + auto operator()(F &&f, T1 const &t1, T2 const &t2, R &&r)DECL_AND_RETURN(fold_on_zip_impl()( + std::forward(f), t1, t2, f(std::get(t1), std::get(t2), std::forward(r)))); + }; + + template struct fold_on_zip_impl<-1, T1, T2> { + template R operator()(F &&f, T1 const &t1, T2 const &t2, R &&r) { return std::forward(r); } + }; + + template + auto fold(F &&f, T1 const &t1, T2 const &t2, R &&r) + DECL_AND_RETURN(fold_on_zip_impl::value - 1, T1, T2>()(std::forward(f), t1, t2, std::forward(r))); + +#endif + + /** + * replace(t,r) + * Given a tuple t, and integers, returns the tuple where the elements at initial position I are replaced by r + */ + template R _get_rpl(T &&x, R &&r, _int) { return std::forward(r); } + template T _get_rpl(T &&x, R &&r, ...) { return std::forward(x); } + + template + auto _replace_impl(Tu &&tu, R &&r, AllIndices _, std14::index_sequence) + RETURN(std::make_tuple(_get_rpl(std::get(tu), r, _)...)); + + template + auto replace(Tu &&tu, R &&r) RETURN(_replace_impl(tu, r, all_indices(), _get_seq())); + + /** + * filter(t) : + * Given a tuple t, and integers, returns the tuple where the elements at initial position I are kept. + */ + template using filter_t = std::tuple>::type...>; + + template filter_t filter(Tu &&tu) { + return filter_t(std::get(std::forward(tu))...); + } + + template filter_t filter(Tu &&tu, std14::index_sequence) { + return filter_t(std::get(std::forward(tu))...); + } + + /** + * filter_out(t) : + * Given a tuple t, and integers, returns the tuple where the elements at initial position I are dropped. + */ + template + AUTO_DECL filter_out(Tu &&tu) RETURN(filter(tu, complement_sequence>::value - 1, I...>())); + + template using filter_out_t = std14::decay_t(std::declval()))>; + /** * t : a tuple * x : anything * push_back (t,x) -> returns new tuple with x append at the end */ - template - auto push_back(T && t, X &&x) DECL_AND_RETURN ( std::tuple_cat(std::forward(t),std::make_tuple(std::forward(x)))); + template + auto push_back(T &&t, X &&x) RETURN(std::tuple_cat(std::forward(t), std::make_tuple(std::forward(x)))); /** * t : a tuple * x : anything * push_front (t,x) -> returns new tuple with x append at the first position */ - template - auto push_front(T && t, X &&x) DECL_AND_RETURN ( std::tuple_cat(std::make_tuple(std::forward(x)),std::forward(t))); + template + auto push_front(T &&t, X &&x) RETURN(std::tuple_cat(std::make_tuple(std::forward(x)), std::forward(t))); + /// To be rewritten .... /** - * apply(f, t) - * f : a callable object - * t a tuple - * Returns : f(t[0], t[1], ...) - * Equivalent to f(*t) in python .... - */ - template struct apply_impl { - template - auto operator()(F && f, T const & t, Args && ... args) - DECL_AND_RETURN( apply_impl()(std::forward(f),t, std::get(t), std::forward(args)...)); - }; - - template<> struct apply_impl<-1> { - template - auto operator()(F && f, T const & t, Args && ... args) DECL_AND_RETURN( std::forward(f)(std::forward(args)...)); - }; - - template - auto apply (F && f, T const & t) DECL_AND_RETURN( apply_impl::value-1>()(std::forward(f),t)); - - //template - //ReturnType apply( ReturnType(*f)(Args...), T const & t) { return apply([f](Args const & ... args) { return (*f)(args...);} ,t);} - - /** - * apply_construct(t) - * F : a class - * t a tuple - * Returns : F { t[0], t[1]} - */ - template struct apply_construct_impl { - template - auto operator()(T const & t, Args && ... args) - DECL_AND_RETURN( apply_construct_impl()(t, std::get(t), std::forward(args)...)); - }; - - template struct apply_construct_impl<-1,F,T> { - template - auto operator()(T const & t, Args && ... args) DECL_AND_RETURN( F{std::forward(args)...}); - }; - - template - auto apply_construct (T const & t) DECL_AND_RETURN( apply_construct_impl::value-1,F,T>()(t)); - - - /** - * for_each(f, t) - * f: a callable object - * t: a tuple - * calls f on all tuple elements: f(x) for all x in t - */ - template struct for_each_impl { - template - void operator()(T const & t, F && f) { - f(std::get::value-1-pos>(t)); - for_each_impl()(t, f); - } - }; - - template<> - struct for_each_impl<0> { - template - void operator() (T const & t, F && f) { f(std::get::value-1>(t)); } - }; - - template - void for_each(T const & t, F && f) { - for_each_impl::value-1>()(t, f); - } - - /* for_each_enumerate(f, t) - * f: a callable object - * t: a tuple - * calls f on all tuple elements: f(x,n) for all x in t - */ - template struct for_each_enumerate_impl { - template - void operator()(T & t, F && f) { - f(std::get>::value-1-pos>(t),std::tuple_size::value-1-pos); - for_each_enumerate_impl()(t, f); - } - }; - - template<> - struct for_each_enumerate_impl<0> { - template - void operator() (T & t, F && f) { f(std::get>::value-1>(t), std::tuple_size>::value-1); } - }; - - template - void for_each_enumerate(T & t, F && f) { - for_each_enumerate_impl>::value-1>()(t, f); - } - - /** - * apply_on_tuple(f, t1,t2) - * f : a callable object - * t1, t2 two tuples of the same size - * Returns : [f(i,j) for i,j in zip(t1,t2)] - */ - template struct apply_on_tuple_impl { - template - auto operator()(F && f, T1 && t1, Args && ... args) - DECL_AND_RETURN( apply_on_tuple_impl()(std::forward(f),std::forward(t1), f(std::get(t1)), std::forward(args)...)); - }; - - template<> struct apply_on_tuple_impl<-1> { - template - auto operator()(F && f, T1 && t1, Args && ... args) DECL_AND_RETURN( std::make_tuple(std::forward(args)...)); - }; - - template - auto apply_on_tuple (F && f,T1 && t1) DECL_AND_RETURN( apply_on_tuple_impl>::value-1>()(std::forward(f),std::forward(t1))); - - /** - * apply_on_zip(f, t1,t2) - * f : a callable object - * t1, t2 two tuples of the same size - * Returns : [f(i,j) for i,j in zip(t1,t2)] - */ - template struct apply_on_zip_impl { - template - auto operator()(F && f, T1 && t1, T2 && t2, Args && ... args) - DECL_AND_RETURN( apply_on_zip_impl()(std::forward(f),std::forward(t1), std::forward(t2), f(std::get(t1),std::get(t2)), std::forward(args)...)); - }; - - template<> struct apply_on_zip_impl<-1> { - template - auto operator()(F && f, T1 && t1, T2 && t2, Args && ... args) DECL_AND_RETURN( std::make_tuple(std::forward(args)...)); - }; - - template - auto apply_on_zip (F && f,T1 && t1, T2 && t2) DECL_AND_RETURN( apply_on_zip_impl>::value-1>()(std::forward(f),std::forward(t1),std::forward(t2))); - - /** - * apply_on_zip(f, t1,t2,t3) - * f : a callable object - * t1, t2 two tuples of the same size - * Returns : [f(i,j) for i,j in zip(t1,t2)] - */ - template struct apply_on_zip3_impl { - template - auto operator()(F && f, T1 && t1, T2 && t2, T3 && t3, Args && ... args) - DECL_AND_RETURN( apply_on_zip3_impl()(std::forward(f),std::forward(t1), std::forward(t2), std::forward(t3), - f(std::get(t1),std::get(t2),std::get(t3)), std::forward(args)...)); - }; - - template<> struct apply_on_zip3_impl<-1> { - template - auto operator()(F && f, T1 && t1, T2 && t2, T3 && t3, Args && ... args) DECL_AND_RETURN( std::make_tuple(std::forward(args)...)); - }; - - template - auto apply_on_zip (F && f,T1 && t1, T2 && t2, T3 && t3) DECL_AND_RETURN( apply_on_zip3_impl::type>::type>::value-1>()(std::forward(f),std::forward(t1),std::forward(t2),std::forward(t3))); - - /** - * call_on_zip(f, t1,t2,t3) - * f : a callable object - * t1, t2, t3 three tuples of the same size - * Returns : void - * Effect : calls f(i,j,k) for all(i,j,k) in zip(t1,t2,t3)] - */ - template struct call_on_zip3_impl { - template - void operator()(F && f, T1 && t1, T2 && t2, T3 && t3) { - f(std::get(std::forward(t1)),std::get(std::forward(t2)),std::get(std::forward(t3))); - call_on_zip3_impl()(std::forward(f),std::forward(t1), std::forward(t2), std::forward(t3)); - } - }; - - template<> struct call_on_zip3_impl<-1> { - template void operator()(F && f, T1 && t1, T2 && t2, T3 && t3){} - }; - - template - void call_on_zip (F && f,T1 && t1, T2 && t2, T3 && t3) { - call_on_zip3_impl::type>::value-1>()(std::forward(f),std::forward(t1),std::forward(t2),std::forward(t3)); - } - - /** - * fold(f, t1, init) - * f : a callable object - * t a tuple - * Returns : f(xN,f(x_N-1,...f(x0,r)) on the tuple - */ - template struct fold_impl { - template - auto operator()(F && f, T && t, R && r ) - DECL_AND_RETURN( fold_impl()(std::forward(f),std::forward(t), f(std::get(t), std::forward(r)))); - }; - - template struct fold_impl { - template R operator()(F && f, T && t, R && r) {return std::forward(r);} - }; - - template - auto fold (F && f,T && t, R && r) DECL_AND_RETURN( fold_impl>::value,std::tuple_size>::value-1,T>()(std::forward(f),std::forward(t),std::forward(r))); - //template - // auto fold (F && f,T const & t, R && r) DECL_AND_RETURN( fold_impl::value,std::tuple_size::value-1,T const>()(std::forward(f),t,std::forward(r))); - - /** - * fold_on_zip(f, t1, t2, init) - * f : a callable object - * t1, t2 two tuples of the same size - * Returns : f(x0,y0,f(x1,y1,,f(....)) for t1 = (x0,x1 ...) and t2 = (y0,y1...). - */ - template struct fold_on_zip_impl { - template - auto operator()(F && f, T1 const & t1, T2 const & t2, R && r ) - DECL_AND_RETURN( fold_on_zip_impl()(std::forward(f),t1,t2, f(std::get(t1), std::get(t2), std::forward(r)))); - }; - - template struct fold_on_zip_impl<-1,T1,T2> { - template R operator()(F && f, T1 const & t1, T2 const & t2, R && r) {return std::forward(r);} - }; - - template - auto fold_on_zip (F && f,T1 const & t1, T2 const & t2, R && r) DECL_AND_RETURN( fold_on_zip_impl::value-1,T1,T2>()(std::forward(f),t1,t2,std::forward(r))); - - /** - * filter(t) : - * Given a tuple t, and integers, returns the tuple where the elements at initial position I are dropped. - */ - - // pos = position in the tuple, c : counter tuplesize-1 ->0, I : position to filter - template struct filter_impl; - - // default case where pos != the first I : increase pos - template struct filter_impl : filter_impl {}; - - // when pos == first I - template struct filter_impl { - template auto operator() (TupleIn const & t, TupleOut && out) const - DECL_AND_RETURN( filter_impl() ( t, push_back(std::forward(out),std::get(t)))); - }; - - template struct filter_impl { - template TupleOut operator() (TupleIn const & t, TupleOut && out) const {return out;} - }; - - template - auto filter(Tu const & tu) DECL_AND_RETURN ( filter_impl<0,std::tuple_size::value-1, I...>()(tu, std::make_tuple())); - - template struct filter_t_tr : std::result_of< filter_impl<0,std::tuple_size::value-1, I...>( Tu, std::tuple<>)>{}; - - template using filter_t = typename filter_t_tr::type; - - /** - * filter_out(t) : - * Given a tuple t, and integers, returns the tuple where the elements at initial position I are dropped. - */ - - // pos = position in the tuple, c : counter tuplesize-1 ->0, I : position to filter - template struct filter_out_impl; - - // default case where pos != the first I : increase pos - template struct filter_out_impl : filter_out_impl {}; - - // when pos == first I - template struct filter_out_impl { - template auto operator() (TupleIn const & t, TupleOut && out) const - DECL_AND_RETURN( filter_out_impl ()( t, push_back(std::forward(out),std::get(t)))); - }; - - template struct filter_out_impl { - template TupleOut operator() (TupleIn const & t, TupleOut && out) const {return out;} - }; - - template - auto filter_out(Tu const & tu) DECL_AND_RETURN ( filter_out_impl<0,std::tuple_size::value-1, I...>()(tu, std::make_tuple())); - - template struct filter_out_t_tr : std::result_of< filter_out_impl<0,std::tuple_size::value-1, I...>( Tu, std::tuple<>)>{}; - - template using filter_out_t = typename filter_out_t_tr::type; - - /** - * inverse_filter(t,x) - * Given a tuple t, and integers, returns the tuple R of size L such that filter(R) == t + * inverse_filter(t,x) + * Given a tuple t, and integers, returns the tuple R of size L such that filter(R) == t * and the missing position are filled with object x. * Precondition (static_assert : sizeof...(I)==size of t) * and max (I) < L @@ -368,7 +416,7 @@ namespace triqs { namespace tuple { }; // put out for clearer error message - template< typename Tu, typename X, int L, int ...I> struct inverse_filter_r_type { + template< typename Tu, typename X, int L, int ...I> struct inverse_filter_r_type { static_assert(sizeof...(I) == std::tuple_size::value, "inverse filter : the # of int must be equal to the tuple size !!"); typedef inverse_filter_impl<0,0,L-1, I...> type; }; @@ -376,9 +424,9 @@ namespace triqs { namespace tuple { template auto inverse_filter(Tu const & tu, X const &x) DECL_AND_RETURN ( typename inverse_filter_r_type::type ()(tu, std::make_tuple(),x)); - /** - * inverse_filter_out(t,x) - * Given a tuple t, and integers, returns the tuple R such that filter_out(R) == t + /** + * inverse_filter_out(t,x) + * Given a tuple t, and integers, returns the tuple R such that filter_out(R) == t * and the missing position are filled with object x. */ @@ -386,7 +434,7 @@ namespace triqs { namespace tuple { template struct inverse_filter_out_impl; // default case where pos != the first I - template struct inverse_filter_out_impl { + template struct inverse_filter_out_impl { template auto operator() (TupleIn const & t, TupleOut && out, X const & x) const DECL_AND_RETURN( inverse_filter_out_impl ()( t, push_back(std::forward(out),std::get(t)),x)); }; @@ -404,72 +452,45 @@ namespace triqs { namespace tuple { template auto inverse_filter_out(Tu const & tu, X const &x) DECL_AND_RETURN ( inverse_filter_out_impl<0,0,std::tuple_size::value+sizeof...(I)-1, I...>()(tu, std::make_tuple(),x)); - /** - * replace(t,r) - * Given a tuple t, and integers, returns the tuple where the elements at initial position I are replaced by r - */ - - // pos = position in the tuple, c : counter tuplesize-1 ->0, I : position to filter - template struct replace_impl; - - // default case where pos != the first I : increase pos - template struct replace_impl { - template auto operator() (TupleIn const & t, TupleOut && out, R const & r) const - DECL_AND_RETURN( replace_impl ()( t, push_back(std::forward(out),r),r)); - }; - - // when pos == first I - template struct replace_impl { - template auto operator() (TupleIn const & t, TupleOut && out, R const & r) const - DECL_AND_RETURN( replace_impl ()( t, push_back(std::forward(out),std::get(t)), r)); - }; - - template struct replace_impl { - template TupleOut operator() (TupleIn const & t, TupleOut && out, R const & r) const {return out;} - }; - - template - auto replace(Tu const & tu, R const &r) DECL_AND_RETURN ( replace_impl<0,std::tuple_size::value-1, I...>()(tu, std::make_tuple(),r)); - - /* - * print a tuple - */ - template struct __s {}; - template void print_tuple_impl (std::ostream& os, T const& t, std::integral_constant ) {} - template void print_tuple_impl (std::ostream& os, T const& t, std::integral_constant ) { - os << std::get(t); - if (rpos>0) os << ','; - print_tuple_impl(os, t, std::integral_constant()); + * print a tuple + */ + inline void _triqs_print_tuple_impl(std::ostream &os) {} + template void _triqs_print_tuple_impl(std::ostream &os, T0 const &x0, T const &... x) { + os << x0; + if (sizeof...(T) > 0) os << ','; + _triqs_print_tuple_impl(os, x...); } -}} -namespace std { - template std::ostream & operator << (std::ostream & os, std::tuple const & t) { - os << "("; - constexpr int L = sizeof...(T); - triqs::tuple::print_tuple_impl(os,t,std::integral_constant()); - return os << ")"; + template + void _triqs_print_tuple(std::ostream &os, std::tuple const &t, std14::index_sequence) { + _triqs_print_tuple_impl(os, std::get(t)...); } } +} namespace std { -namespace c14 { - - // a little helper class to wait for the correction that tuple construct is NOT explicit - template class tuple : public std::tuple { - public: - template tuple(Args2 &&... args2) : std::tuple(std::forward(args2)...) {} - }; - } - - // minimal hack to get the metaprogramming work with this tuple too.... - template - auto get(c14::tuple const &t) DECL_AND_RETURN(std::get(static_cast>(t))); - - template class tuple_size> : public tuple_size> {}; +template std::ostream &operator<<(std::ostream &os, std::tuple const &t) { + os << "("; + triqs::tuple::_triqs_print_tuple(os, t, std14::make_index_sequence()); + return os << ")"; } -#endif +// do not move this up.... +namespace c14 { + + // a little helper class to wait for the correction that tuple construct is NOT explicit + template class tuple : public std::tuple { + public: + template tuple(Args2 &&... args2) : std::tuple(std::forward(args2)...) {} + }; +} + +// minimal hack to get the metaprogramming work with this tuple too.... +template +auto get(c14::tuple const &t) DECL_AND_RETURN(std::get(static_cast>(t))); + +template class tuple_size> : public tuple_size> {}; +}