mirror of
https://github.com/triqs/dft_tools
synced 2024-12-25 05:43:40 +01:00
tuple tools : simplify
- simplify implementation of several functions. - clean API, rename, etc... - add more documentation
This commit is contained in:
parent
6d12c4b7f6
commit
36a60ce529
@ -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::
|
||||
..
|
||||
.. 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.
|
||||
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<typename Function, typename Tuple> 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<typename Function, typename Tuple> 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 <typename F, typename T0, typename T1> void for_each_zip(F &&f, T0 &&t0, T1 &&t1);
|
||||
template <typename F, typename T0, typename T1, typename T2> 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 <typename T, typename F> 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 <typename F, typename T, typename R>
|
||||
decltype(auto) fold(F &&f, T &&t, R &&r);
|
||||
|
||||
(2) template <typename F, typename T0, typename T1, typename R>
|
||||
decltype(auto) fold(F &&f, T0 &&t0, T1 &&t1, R &&r);
|
||||
|
||||
*Returns*::
|
||||
|
||||
f(get<N>(t),
|
||||
f(get<N-1>(t),
|
||||
...,
|
||||
f(get<0>(t),r))) (1)
|
||||
|
||||
f(get<N>(t0), get<N>(t1),
|
||||
f(get<N-1>(t0), get<N-1>(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<typename ... T> TU reverse(std::tuple<T...> && x);
|
||||
template<typename ... T> TU reverse(std::tuple<T...> & x);
|
||||
template<typename ... T> TU reverse(std::tuple<T...> 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 <typename F> 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 <typename F> struct _called_on_tuple {
|
||||
F _f;
|
||||
template <typename Tu> decltype(auto) operator()(Tu &&tu) {
|
||||
return apply(_f, std::forward<Tu>(tu));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F> _called_on_tuple<F> called_on_tuple(F &&f) {
|
||||
return {std::forward<F>(f)};
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
#include <triqs/utility/tuple_tools.hpp>
|
||||
#include <iostream>
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,10 @@
|
||||
#include <triqs/utility/tuple_tools.hpp>
|
||||
#include <iostream>
|
||||
|
||||
struct print_t {
|
||||
template <typename T> 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<<x<<" ";});
|
||||
triqs::tuple::for_each(t, l);
|
||||
}
|
||||
|
||||
|
11
doc/reference/c++/utilities/tupletools_2.cpp
Normal file
11
doc/reference/c++/utilities/tupletools_2.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <triqs/utility/tuple_tools.hpp>
|
||||
#include <iostream>
|
||||
|
||||
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);
|
||||
}
|
||||
|
12
doc/reference/c++/utilities/tupletools_3.cpp
Normal file
12
doc/reference/c++/utilities/tupletools_3.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include <triqs/utility/tuple_tools.hpp>
|
||||
#include <iostream>
|
||||
|
||||
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;
|
||||
}
|
||||
|
24
doc/reference/c++/utilities/tupletools_4.cpp
Normal file
24
doc/reference/c++/utilities/tupletools_4.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include <triqs/utility/tuple_tools.hpp>
|
||||
#include <iostream>
|
||||
|
||||
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;
|
||||
}
|
||||
|
11
doc/reference/c++/utilities/tupletools_called.cpp
Normal file
11
doc/reference/c++/utilities/tupletools_called.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <triqs/utility/tuple_tools.hpp>
|
||||
#include <iostream>
|
||||
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;
|
||||
}
|
||||
|
11
doc/reference/c++/utilities/tupletools_reverse.cpp
Normal file
11
doc/reference/c++/utilities/tupletools_reverse.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <triqs/utility/tuple_tools.hpp>
|
||||
#include <iostream>
|
||||
|
||||
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);
|
||||
}
|
@ -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<typename std::remove_reference<decltype(G_w_wn_sl0_a.mesh())>::type, const gf_mesh<imfreq>>::value, "oops");
|
||||
//auto G_w_wn_curry0_a = curry0(G_w_wn);
|
||||
//auto G_w_wn_sl0_a = slice_mesh0(G_w_wn(), 8);
|
||||
|
@ -19,7 +19,6 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
#include <triqs/utility/tuple_tools.hpp>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
#include <functional>
|
||||
@ -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<typename T>
|
||||
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<TY, decltype(triqs::tuple::filter<0,2,3>(t))>::value, "EEE");
|
||||
}
|
||||
|
||||
{ // filter
|
||||
|
@ -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; }
|
||||
|
@ -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<size_t, dim> shape() const {
|
||||
utility::mini_vector<size_t, dim> 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 <class Archive> 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);
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ namespace gfs {
|
||||
{
|
||||
static constexpr int R = sizeof...(Args);
|
||||
// build the evaluators, as a tuple of ( evaluator<Ms> ( 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<R - 1>(evals)(make_binder<R - 2>(g, std::make_tuple(), evals));
|
||||
}
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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,328 +18,376 @@
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_UTILITY_TUPLE_TOOLS_H
|
||||
#define TRIQS_UTILITY_TUPLE_TOOLS_H
|
||||
#pragma once
|
||||
#include<triqs/utility/macros.hpp>
|
||||
#include <tuple>
|
||||
#include "./c14.hpp"
|
||||
#include <sstream>
|
||||
#include <tuple>
|
||||
#include <ostream>
|
||||
|
||||
// adding to the std lib the reversed lazy tuple...
|
||||
// overloading & specializing only the functions needed here.
|
||||
namespace std {
|
||||
|
||||
// Reverse
|
||||
template<typename TU> struct _triqs_reversed_tuple {TU _x;};
|
||||
|
||||
template<typename ... T> _triqs_reversed_tuple<std::tuple<T...>> reverse(std::tuple<T...> && x) { return {move(x)};}
|
||||
template<typename ... T> _triqs_reversed_tuple<std::tuple<T...>&> reverse(std::tuple<T...> & x) { return {x};}
|
||||
template<typename ... T> _triqs_reversed_tuple<std::tuple<T...>const &> reverse(std::tuple<T...> const & x) { return {x};}
|
||||
|
||||
template<int pos, typename TU> auto get(_triqs_reversed_tuple<TU> const & t)
|
||||
DECL_AND_RETURN(std::get<std::tuple_size<std14::decay_t<TU>>::value-1-pos>(t._x));
|
||||
template<int pos, typename TU> AUTO_DECL get(_triqs_reversed_tuple<TU> const & t)
|
||||
RETURN(std::get<std::tuple_size<std14::decay_t<TU>>::value-1-pos>(t._x));
|
||||
|
||||
template<int pos, typename TU> auto get(_triqs_reversed_tuple<TU> & t)
|
||||
DECL_AND_RETURN(std::get<std::tuple_size<std14::decay_t<TU>>::value-1-pos>(t._x));
|
||||
template<int pos, typename TU> AUTO_DECL get(_triqs_reversed_tuple<TU> & t)
|
||||
RETURN(std::get<std::tuple_size<std14::decay_t<TU>>::value-1-pos>(t._x));
|
||||
|
||||
template<int pos, typename TU> auto get(_triqs_reversed_tuple<TU> && t)
|
||||
DECL_AND_RETURN(std::get<std::tuple_size<std14::decay_t<TU>>::value-1-pos>(move(t)._x));
|
||||
template<int pos, typename TU> AUTO_DECL get(_triqs_reversed_tuple<TU> && t)
|
||||
RETURN(std::get<std::tuple_size<std14::decay_t<TU>>::value-1-pos>(move(t)._x));
|
||||
|
||||
template <typename TU> class tuple_size<_triqs_reversed_tuple<TU>> : public tuple_size<std14::decay_t<TU>> {};
|
||||
|
||||
// Zipped tuple:
|
||||
template <typename... T> struct _triqs_zipped_tuple {
|
||||
std::tuple<T...> _tu;
|
||||
template <typename... U> _triqs_zipped_tuple(U &&... u) : _tu(std::forward<U>(u)...) {}
|
||||
|
||||
template <size_t I, size_t... Is> auto _get(std::c14::index_sequence<Is...>) RETURN(std::tie(std::get<I>(std::get<Is>(_tu))...));
|
||||
template <size_t I, size_t... Is> auto _get(std::c14::index_sequence<Is...>) const RETURN(std::tie(std::get<I>(std::get<Is>(_tu))...));
|
||||
};
|
||||
|
||||
template <size_t I, typename... T>
|
||||
AUTO_DECL get(_triqs_zipped_tuple<T...> const &tu) RETURN(tu.template _get<I>(std14::make_index_sequence<sizeof...(T)>()));
|
||||
|
||||
template <typename T0, typename... T> struct tuple_size<_triqs_zipped_tuple<T0, T...>> : public std::tuple_size<std14::decay_t<T0>> {};
|
||||
|
||||
template <typename... T> _triqs_zipped_tuple<T...> zip(T &&... x) {
|
||||
return {std::forward<T>(x)...};
|
||||
}
|
||||
|
||||
template<typename TU> class tuple_size<_triqs_reversed_tuple<TU>> : public tuple_size<std14::decay_t<TU>>{};
|
||||
}
|
||||
|
||||
|
||||
namespace triqs { namespace tuple {
|
||||
|
||||
/// _get_seq<T>() : from a tuple T, return the index sequence of the tuple length
|
||||
template <typename T> std14::make_index_sequence<std::tuple_size<std14::decay_t<T>>::value> _get_seq() {
|
||||
return {};
|
||||
}
|
||||
|
||||
/// _get_seq_len<T> : constexpr : return the length of the tuple
|
||||
template <typename Tu> constexpr int _get_seq_len() { return std::tuple_size<std14::decay_t<Tu>>::value; }
|
||||
|
||||
/// basic tools
|
||||
template <int N> struct _int {};
|
||||
template <int... Is> struct all_indices : _int<Is>... {};
|
||||
|
||||
// --- impl complement -----
|
||||
template <int N, typename hole_seq, int... Is> struct complement_sequence_impl {
|
||||
static complement_sequence_impl<N - 1, hole_seq, Is...> get(_int<N>) {}
|
||||
static complement_sequence_impl<N - 1, hole_seq, N, Is...> get(...) {}
|
||||
using type = typename decltype(get(hole_seq()))::type;
|
||||
};
|
||||
|
||||
template <typename hole_seq, int... Is> struct complement_sequence_impl<-1, hole_seq, Is...> {
|
||||
using type = std14::index_sequence<Is...>;
|
||||
};
|
||||
|
||||
/// An index sequence of elements of [0,N-1] which are NOT Is
|
||||
template <int N, int... Is> using complement_sequence = typename complement_sequence_impl<N, all_indices<Is...>>::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 <typename F, typename T, size_t... Is>
|
||||
AUTO_DECL apply_impl(F &&f, T &&t, std14::index_sequence<Is...>) RETURN(f(std::get<Is>(std::forward<T>(t))...));
|
||||
|
||||
template <typename F, typename T>
|
||||
AUTO_DECL apply(F &&f, T &&t) RETURN(apply_impl(std::forward<F>(f), std::forward<T>(t), _get_seq<T>()));
|
||||
|
||||
/**
|
||||
* apply_construct<C>(t)
|
||||
* C : a class
|
||||
* t a tuple
|
||||
* Returns : C{t0, t1, ....}
|
||||
*/
|
||||
template <typename C, typename T, size_t... Is>
|
||||
AUTO_DECL apply_construct_impl(T &&t, std14::index_sequence<Is...>) RETURN(C{std::get<Is>(std::forward<T>(t))...});
|
||||
|
||||
template <typename C, typename T>
|
||||
AUTO_DECL apply_construct(T &&t) RETURN(apply_construct_impl<C>(std::forward<T>(t), _get_seq<T>()));
|
||||
|
||||
/**
|
||||
* 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 <typename F> struct _called_on_tuple {
|
||||
F _f;
|
||||
template <typename Tu> AUTO_DECL operator()(Tu &&tu) RETURN(apply(_f, std::forward<Tu>(tu)));
|
||||
};
|
||||
|
||||
template <typename F> _called_on_tuple<F> called_on_tuple(F &&f) {
|
||||
return {std::forward<F>(f)};
|
||||
}
|
||||
|
||||
// Implementation tools
|
||||
// _for_each_impl (f, x0, x1, ..., xn) calls f(x0); f(x1); ... f(xn); IN THIS ORDER
|
||||
template <typename F> void _for_each_impl(F &&f) {}
|
||||
|
||||
template <typename F, typename T0, typename... T> void _for_each_impl(F &&f, T0 &&x0, T &&... x) {
|
||||
f(std::forward<T0>(x0));
|
||||
_for_each_impl(f, std::forward<T>(x)...);
|
||||
}
|
||||
|
||||
// _for_each_apply_impl (f, t0, t1, ..., tn) calls apply(f,x0); apply(f,t1); ... apply(f,tn);
|
||||
template <typename F> void _for_each_apply_impl(F &&f) {}
|
||||
|
||||
template <typename F, typename T0, typename... T> void _for_each_apply_impl(F &&f, T0 &&t0, T &&... t) {
|
||||
apply(f, std::forward<T0>(t0));
|
||||
_for_each_apply_impl(f, std::forward<T>(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 <typename F, typename T, size_t... Is> void for_each_impl(F &&f, T &&t, std14::index_sequence<Is...>) {
|
||||
_for_each_impl(f, std::get<Is>(t)...);
|
||||
}
|
||||
|
||||
template <typename T, typename F> void for_each(T &&t, F &&f) { for_each_impl(f, std::forward<T>(t), _get_seq<T>()); }
|
||||
|
||||
/* 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 <typename F, typename T, size_t... Is> void _for_each_enum_impl(F &&f, T &&t, std14::index_sequence<Is...>) {
|
||||
_for_each_apply_impl(f, std::tuple<int, decltype(std::get<Is>(t))>(Is, std::get<Is>(t))...);
|
||||
// not make_tuple here, we keep the ref given by the get
|
||||
}
|
||||
|
||||
template <typename T, typename F> void for_each_enumerate(T &&t, F &&f) {
|
||||
_for_each_enum_impl(f, std::forward<T>(t), _get_seq<T>());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 <typename F, typename T0, typename T1, size_t... Is>
|
||||
void _for_each_zip_impl(std14::index_sequence<Is...>, F &&f, T0 &&t0, T1 &&t1) {
|
||||
_for_each_impl(called_on_tuple(std::forward<F>(f)), std::tie(std::get<Is>(t0), std::get<Is>(t1))...);
|
||||
}
|
||||
|
||||
template <typename F, typename T0, typename T1> void for_each_zip(F &&f, T0 &&t0, T1 &&t1) {
|
||||
_for_each_zip_impl(_get_seq<T0>(), std::forward<F>(f), std::forward<T0>(t0), std::forward<T1>(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 <typename F, typename T0, typename T1, typename T2, size_t... Is>
|
||||
void _for_each_zip_impl(std14::index_sequence<Is...>, F &&f, T0 &&t0, T1 &&t1, T2 &&t2) {
|
||||
_for_each_impl(called_on_tuple(std::forward<F>(f)), std::tie(std::get<Is>(t0), std::get<Is>(t1), std::get<Is>(t2))...);
|
||||
}
|
||||
|
||||
template <typename F, typename T0, typename T1, typename T2> void for_each_zip(F &&f, T0 &&t0, T1 &&t1, T2 &&t2) {
|
||||
_for_each_zip_impl(_get_seq<T0>(), std::forward<F>(f), std::forward<T0>(t0), std::forward<T1>(t1), std::forward<T2>(t2));
|
||||
}
|
||||
|
||||
/**
|
||||
* map(f, t)
|
||||
* f : a callable object
|
||||
* t tuple
|
||||
* Returns : [f(i) for i in t]
|
||||
*/
|
||||
template <typename F, typename T, size_t... Is>
|
||||
AUTO_DECL _map_impl(F &&f, T &&t, std14::index_sequence<Is...>)
|
||||
RETURN(std::make_tuple(std::forward<F>(f)(std::get<Is>(t))...));
|
||||
|
||||
template <typename T, typename F>
|
||||
AUTO_DECL map(F &&f, T &&t) RETURN(_map_impl(std::forward<F>(f), std::forward<T>(t), _get_seq<T>()));
|
||||
|
||||
/**
|
||||
* 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 <typename F, typename T0, typename T1, size_t... Is>
|
||||
auto _map_impl(F &&f, T0 &&t0, T1 &&t1, std14::index_sequence<Is...>)
|
||||
RETURN(std::make_tuple(std::forward<F>(f)(std::get<Is>(t0), std::get<Is>(t1))...));
|
||||
|
||||
template <typename T0, typename T1, typename F>
|
||||
auto map_on_zip(F &&f, T0 &&t0, T1 &&t1)
|
||||
RETURN(_map_impl(std::forward<F>(f), std::forward<T0>(t0), std::forward<T1>(t1), _get_seq<T0>()));
|
||||
|
||||
template <typename T0, typename T1, typename F>
|
||||
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 <typename F, typename T0, typename T1, typename T2, size_t... Is>
|
||||
auto _map_impl(F &&f, T0 &&t0, T1 &&t1, T2 &&t2, std14::index_sequence<Is...>)
|
||||
RETURN(std::make_tuple(std::forward<F>(f)(std::get<Is>(t0), std::get<Is>(t1), std::get<Is>(t2))...));
|
||||
|
||||
template <typename T0, typename T1, typename T2, typename F>
|
||||
auto map_on_zip(F &&f, T0 &&t0, T1 &&t1, T2 &&t2)
|
||||
RETURN(_map_impl(std::forward<F>(f), std::forward<T0>(t0), std::forward<T1>(t1), std::forward<T2>(t2), _get_seq<T0>()));
|
||||
|
||||
/**
|
||||
* 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 <int pos, typename F, typename T, typename R> decltype(auto) fold_impl(_int<pos>, F &&f, T &&t, R &&r) {
|
||||
return fold_impl(_int<pos - 1>(), std::forward<F>(f), std::forward<T>(t),
|
||||
f(std::get<_get_seq_len<T>() - 1 - pos>(t), std::forward<R>(r)));
|
||||
}
|
||||
template <typename F, typename T, typename R> R fold_impl(_int<-1>, F &&f, T &&t, R &&r) { return std::forward<R>(r); }
|
||||
|
||||
template <typename F, typename T, typename R> decltype(auto) fold(F &&f, T &&t, R &&r) {
|
||||
return fold_impl(_int<_get_seq_len<T>() - 1>(), std::forward<F>(f), std::forward<T>(t), std::forward<R>(r));
|
||||
}
|
||||
#else
|
||||
// old implementation, not modified for C++11
|
||||
|
||||
template <int N, int pos, typename T> struct fold_impl {
|
||||
template <typename F, typename R>
|
||||
auto operator()(F &&f, T &&t,
|
||||
R &&r)DECL_AND_RETURN(fold_impl<N, pos - 1, T>()(std::forward<F>(f), std::forward<T>(t),
|
||||
f(std::get<N - 1 - pos>(t), std::forward<R>(r))));
|
||||
};
|
||||
|
||||
template <int N, typename T> struct fold_impl<N, -1, T> {
|
||||
template <typename F, typename R> R operator()(F &&f, T &&t, R &&r) { return std::forward<R>(r); }
|
||||
};
|
||||
|
||||
template <typename F, typename T, typename R>
|
||||
auto fold(F &&f, T &&t, R &&r)
|
||||
DECL_AND_RETURN(fold_impl<std::tuple_size<std::c14::decay_t<T>>::value, std::tuple_size<std::c14::decay_t<T>>::value - 1,
|
||||
T>()(std::forward<F>(f), std::forward<T>(t), std::forward<R>(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 <int pos, typename F, typename T0, typename T1, typename R>
|
||||
decltype(auto) fold_impl(_int<pos>, F &&f, T0 &&t0, T1 &&t1, R &&r) {
|
||||
constexpr int n = _get_seq_len<T0>() - 1 - pos;
|
||||
return fold_impl(_int<pos - 1>(), std::forward<F>(f), std::forward<T0>(t0), std::forward<T1>(t1),
|
||||
f(std::get<n>(t0), std::get<n>(t1), std::forward<R>(r)));
|
||||
}
|
||||
|
||||
template <typename F, typename T0, typename T1, typename R> R fold_impl(_int<-1>, F &&f, T0 &&t0, T1 &&t1, R &&r) {
|
||||
return std::forward<R>(r);
|
||||
}
|
||||
|
||||
template <typename F, typename T0, typename T1, typename R> decltype(auto) fold(F &&f, T0 &&t0, T1 &&t1, R &&r) {
|
||||
return fold_impl(_int<_get_seq_len<T0>() - 1>(), std::forward<F>(f), std::forward<T0>(t0), std::forward<T1>(t1),
|
||||
std::forward<R>(r));
|
||||
}
|
||||
#else
|
||||
// old implementation, not modified for C++11
|
||||
|
||||
template <int pos, typename T1, typename T2> struct fold_on_zip_impl {
|
||||
template <typename F, typename R>
|
||||
auto operator()(F &&f, T1 const &t1, T2 const &t2, R &&r)DECL_AND_RETURN(fold_on_zip_impl<pos - 1, T1, T2>()(
|
||||
std::forward<F>(f), t1, t2, f(std::get<pos>(t1), std::get<pos>(t2), std::forward<R>(r))));
|
||||
};
|
||||
|
||||
template <typename T1, typename T2> struct fold_on_zip_impl<-1, T1, T2> {
|
||||
template <typename F, typename R> R operator()(F &&f, T1 const &t1, T2 const &t2, R &&r) { return std::forward<R>(r); }
|
||||
};
|
||||
|
||||
template <typename F, typename T1, typename T2, typename R>
|
||||
auto fold(F &&f, T1 const &t1, T2 const &t2, R &&r)
|
||||
DECL_AND_RETURN(fold_on_zip_impl<std::tuple_size<T1>::value - 1, T1, T2>()(std::forward<F>(f), t1, t2, std::forward<R>(r)));
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* replace<int ... I>(t,r)
|
||||
* Given a tuple t, and integers, returns the tuple where the elements at initial position I are replaced by r
|
||||
*/
|
||||
template <int I, typename T, typename R> R _get_rpl(T &&x, R &&r, _int<I>) { return std::forward<R>(r); }
|
||||
template <int I, typename T, typename R> T _get_rpl(T &&x, R &&r, ...) { return std::forward<T>(x); }
|
||||
|
||||
template <size_t... Is, typename Tu, typename R, typename AllIndices>
|
||||
auto _replace_impl(Tu &&tu, R &&r, AllIndices _, std14::index_sequence<Is...>)
|
||||
RETURN(std::make_tuple(_get_rpl<Is>(std::get<Is>(tu), r, _)...));
|
||||
|
||||
template <int... I, typename Tu, typename R>
|
||||
auto replace(Tu &&tu, R &&r) RETURN(_replace_impl(tu, r, all_indices<I...>(), _get_seq<Tu>()));
|
||||
|
||||
/**
|
||||
* filter<int ... I>(t) :
|
||||
* Given a tuple t, and integers, returns the tuple where the elements at initial position I are kept.
|
||||
*/
|
||||
template <typename Tu, size_t... I> using filter_t = std::tuple<typename std::tuple_element<I, std14::decay_t<Tu>>::type...>;
|
||||
|
||||
template <size_t... I, typename Tu> filter_t<Tu, I...> filter(Tu &&tu) {
|
||||
return filter_t<Tu, I...>(std::get<I>(std::forward<Tu>(tu))...);
|
||||
}
|
||||
|
||||
template <size_t... I, typename Tu> filter_t<Tu, I...> filter(Tu &&tu, std14::index_sequence<I...>) {
|
||||
return filter_t<Tu, I...>(std::get<I>(std::forward<Tu>(tu))...);
|
||||
}
|
||||
|
||||
/**
|
||||
* filter_out<int ... I>(t) :
|
||||
* Given a tuple t, and integers, returns the tuple where the elements at initial position I are dropped.
|
||||
*/
|
||||
template <int... I, typename Tu>
|
||||
AUTO_DECL filter_out(Tu &&tu) RETURN(filter(tu, complement_sequence<std::tuple_size<std14::decay_t<Tu>>::value - 1, I...>()));
|
||||
|
||||
template <typename Tu, int... I> using filter_out_t = std14::decay_t<decltype(filter_out<I...>(std::declval<Tu>()))>;
|
||||
|
||||
/**
|
||||
* t : a tuple
|
||||
* x : anything
|
||||
* push_back (t,x) -> returns new tuple with x append at the end
|
||||
*/
|
||||
template<typename T, typename X>
|
||||
auto push_back(T && t, X &&x) DECL_AND_RETURN ( std::tuple_cat(std::forward<T>(t),std::make_tuple(std::forward<X>(x))));
|
||||
template <typename T, typename X>
|
||||
auto push_back(T &&t, X &&x) RETURN(std::tuple_cat(std::forward<T>(t), std::make_tuple(std::forward<X>(x))));
|
||||
|
||||
/**
|
||||
* t : a tuple
|
||||
* x : anything
|
||||
* push_front (t,x) -> returns new tuple with x append at the first position
|
||||
*/
|
||||
template<typename T, typename X>
|
||||
auto push_front(T && t, X &&x) DECL_AND_RETURN ( std::tuple_cat(std::make_tuple(std::forward<X>(x)),std::forward<T>(t)));
|
||||
|
||||
/**
|
||||
* apply(f, t)
|
||||
* f : a callable object
|
||||
* t a tuple
|
||||
* Returns : f(t[0], t[1], ...)
|
||||
* Equivalent to f(*t) in python ....
|
||||
*/
|
||||
template<int pos> struct apply_impl {
|
||||
template<typename F, typename T, typename ... Args>
|
||||
auto operator()(F && f, T const & t, Args && ... args)
|
||||
DECL_AND_RETURN( apply_impl<pos-1>()(std::forward<F>(f),t, std::get<pos>(t), std::forward<Args>(args)...));
|
||||
};
|
||||
|
||||
template<> struct apply_impl<-1> {
|
||||
template<typename F, typename T, typename ... Args>
|
||||
auto operator()(F && f, T const & t, Args && ... args) DECL_AND_RETURN( std::forward<F>(f)(std::forward<Args>(args)...));
|
||||
};
|
||||
|
||||
template<typename F, typename T>
|
||||
auto apply (F && f, T const & t) DECL_AND_RETURN( apply_impl<std::tuple_size<T>::value-1>()(std::forward<F>(f),t));
|
||||
|
||||
//template <typename T, typename ReturnType, typename... Args>
|
||||
//ReturnType apply( ReturnType(*f)(Args...), T const & t) { return apply([f](Args const & ... args) { return (*f)(args...);} ,t);}
|
||||
|
||||
/**
|
||||
* apply_construct<F>(t)
|
||||
* F : a class
|
||||
* t a tuple
|
||||
* Returns : F { t[0], t[1]}
|
||||
*/
|
||||
template<int pos, typename F, typename T> struct apply_construct_impl {
|
||||
template<typename ... Args>
|
||||
auto operator()(T const & t, Args && ... args)
|
||||
DECL_AND_RETURN( apply_construct_impl<pos-1,F,T>()(t, std::get<pos>(t), std::forward<Args>(args)...));
|
||||
};
|
||||
|
||||
template<typename F, typename T> struct apply_construct_impl<-1,F,T> {
|
||||
template<typename ... Args>
|
||||
auto operator()(T const & t, Args && ... args) DECL_AND_RETURN( F{std::forward<Args>(args)...});
|
||||
};
|
||||
|
||||
template<typename F, typename T>
|
||||
auto apply_construct (T const & t) DECL_AND_RETURN( apply_construct_impl<std::tuple_size<T>::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<int pos> struct for_each_impl {
|
||||
template<typename T, typename F>
|
||||
void operator()(T const & t, F && f) {
|
||||
f(std::get<std::tuple_size<T>::value-1-pos>(t));
|
||||
for_each_impl<pos-1>()(t, f);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct for_each_impl<0> {
|
||||
template<typename T, typename F>
|
||||
void operator() (T const & t, F && f) { f(std::get<std::tuple_size<T>::value-1>(t)); }
|
||||
};
|
||||
|
||||
template<typename T, typename F>
|
||||
void for_each(T const & t, F && f) {
|
||||
for_each_impl<std::tuple_size<T>::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<int pos> struct for_each_enumerate_impl {
|
||||
template<typename T, typename F>
|
||||
void operator()(T & t, F && f) {
|
||||
f(std::get<std::tuple_size<std::c14::decay_t<T>>::value-1-pos>(t),std::tuple_size<T>::value-1-pos);
|
||||
for_each_enumerate_impl<pos-1>()(t, f);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct for_each_enumerate_impl<0> {
|
||||
template<typename T, typename F>
|
||||
void operator() (T & t, F && f) { f(std::get<std::tuple_size<std::c14::decay_t<T>>::value-1>(t), std::tuple_size<std::c14::decay_t<T>>::value-1); }
|
||||
};
|
||||
|
||||
template<typename T, typename F>
|
||||
void for_each_enumerate(T & t, F && f) {
|
||||
for_each_enumerate_impl<std::tuple_size<std::c14::decay_t<T>>::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<int pos> struct apply_on_tuple_impl {
|
||||
template<typename F, typename T1, typename ... Args>
|
||||
auto operator()(F && f, T1 && t1, Args && ... args)
|
||||
DECL_AND_RETURN( apply_on_tuple_impl<pos-1>()(std::forward<F>(f),std::forward<T1>(t1), f(std::get<pos>(t1)), std::forward<Args>(args)...));
|
||||
};
|
||||
|
||||
template<> struct apply_on_tuple_impl<-1> {
|
||||
template<typename F, typename T1, typename ... Args>
|
||||
auto operator()(F && f, T1 && t1, Args && ... args) DECL_AND_RETURN( std::make_tuple(std::forward<Args>(args)...));
|
||||
};
|
||||
|
||||
template<typename F, typename T1>
|
||||
auto apply_on_tuple (F && f,T1 && t1) DECL_AND_RETURN( apply_on_tuple_impl<std::tuple_size<std14::decay_t<T1>>::value-1>()(std::forward<F>(f),std::forward<T1>(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<int pos> struct apply_on_zip_impl {
|
||||
template<typename F, typename T1, typename T2, typename ... Args>
|
||||
auto operator()(F && f, T1 && t1, T2 && t2, Args && ... args)
|
||||
DECL_AND_RETURN( apply_on_zip_impl<pos-1>()(std::forward<F>(f),std::forward<T1>(t1), std::forward<T2>(t2), f(std::get<pos>(t1),std::get<pos>(t2)), std::forward<Args>(args)...));
|
||||
};
|
||||
|
||||
template<> struct apply_on_zip_impl<-1> {
|
||||
template<typename F, typename T1, typename T2, typename ... Args>
|
||||
auto operator()(F && f, T1 && t1, T2 && t2, Args && ... args) DECL_AND_RETURN( std::make_tuple(std::forward<Args>(args)...));
|
||||
};
|
||||
|
||||
template<typename F, typename T1, typename T2>
|
||||
auto apply_on_zip (F && f,T1 && t1, T2 && t2) DECL_AND_RETURN( apply_on_zip_impl<std::tuple_size<std14::decay_t<T1>>::value-1>()(std::forward<F>(f),std::forward<T1>(t1),std::forward<T2>(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<int pos> struct apply_on_zip3_impl {
|
||||
template<typename F, typename T1, typename T2, typename T3, typename ... Args>
|
||||
auto operator()(F && f, T1 && t1, T2 && t2, T3 && t3, Args && ... args)
|
||||
DECL_AND_RETURN( apply_on_zip3_impl<pos-1>()(std::forward<F>(f),std::forward<T1>(t1), std::forward<T2>(t2), std::forward<T3>(t3),
|
||||
f(std::get<pos>(t1),std::get<pos>(t2),std::get<pos>(t3)), std::forward<Args>(args)...));
|
||||
};
|
||||
|
||||
template<> struct apply_on_zip3_impl<-1> {
|
||||
template<typename F, typename T1, typename T2, typename T3,typename ... Args>
|
||||
auto operator()(F && f, T1 && t1, T2 && t2, T3 && t3, Args && ... args) DECL_AND_RETURN( std::make_tuple(std::forward<Args>(args)...));
|
||||
};
|
||||
|
||||
template<typename F, typename T1, typename T2, typename T3>
|
||||
auto apply_on_zip (F && f,T1 && t1, T2 && t2, T3 && t3) DECL_AND_RETURN( apply_on_zip3_impl<std::tuple_size<typename std::remove_const<typename std::remove_reference<T1>::type>::type>::value-1>()(std::forward<F>(f),std::forward<T1>(t1),std::forward<T2>(t2),std::forward<T3>(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<int pos> struct call_on_zip3_impl {
|
||||
template<typename F, typename T1, typename T2, typename T3>
|
||||
void operator()(F && f, T1 && t1, T2 && t2, T3 && t3) {
|
||||
f(std::get<pos>(std::forward<T1>(t1)),std::get<pos>(std::forward<T2>(t2)),std::get<pos>(std::forward<T3>(t3)));
|
||||
call_on_zip3_impl<pos-1>()(std::forward<F>(f),std::forward<T1>(t1), std::forward<T2>(t2), std::forward<T3>(t3));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct call_on_zip3_impl<-1> {
|
||||
template<typename F, typename T1, typename T2, typename T3> void operator()(F && f, T1 && t1, T2 && t2, T3 && t3){}
|
||||
};
|
||||
|
||||
template<typename F, typename T1, typename T2, typename T3>
|
||||
void call_on_zip (F && f,T1 && t1, T2 && t2, T3 && t3) {
|
||||
call_on_zip3_impl<std::tuple_size<typename std::remove_reference<T1>::type>::value-1>()(std::forward<F>(f),std::forward<T1>(t1),std::forward<T2>(t2),std::forward<T3>(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<int N, int pos, typename T> struct fold_impl {
|
||||
template<typename F, typename R>
|
||||
auto operator()(F && f, T && t, R && r )
|
||||
DECL_AND_RETURN( fold_impl<N,pos-1,T>()(std::forward<F>(f),std::forward<T>(t), f(std::get<N-1-pos>(t), std::forward<R>(r))));
|
||||
};
|
||||
|
||||
template<int N, typename T> struct fold_impl<N, -1,T> {
|
||||
template<typename F, typename R> R operator()(F && f, T && t, R && r) {return std::forward<R>(r);}
|
||||
};
|
||||
|
||||
template<typename F, typename T, typename R>
|
||||
auto fold (F && f,T && t, R && r) DECL_AND_RETURN( fold_impl<std::tuple_size<std::c14::decay_t<T>>::value,std::tuple_size<std::c14::decay_t<T>>::value-1,T>()(std::forward<F>(f),std::forward<T>(t),std::forward<R>(r)));
|
||||
//template<typename F, typename T, typename R>
|
||||
// auto fold (F && f,T const & t, R && r) DECL_AND_RETURN( fold_impl<std::tuple_size<T>::value,std::tuple_size<T>::value-1,T const>()(std::forward<F>(f),t,std::forward<R>(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<int pos, typename T1, typename T2> struct fold_on_zip_impl {
|
||||
template<typename F, typename R>
|
||||
auto operator()(F && f, T1 const & t1, T2 const & t2, R && r )
|
||||
DECL_AND_RETURN( fold_on_zip_impl<pos-1,T1,T2>()(std::forward<F>(f),t1,t2, f(std::get<pos>(t1), std::get<pos>(t2), std::forward<R>(r))));
|
||||
};
|
||||
|
||||
template<typename T1, typename T2> struct fold_on_zip_impl<-1,T1,T2> {
|
||||
template<typename F, typename R> R operator()(F && f, T1 const & t1, T2 const & t2, R && r) {return std::forward<R>(r);}
|
||||
};
|
||||
|
||||
template<typename F, typename T1, typename T2, typename R>
|
||||
auto fold_on_zip (F && f,T1 const & t1, T2 const & t2, R && r) DECL_AND_RETURN( fold_on_zip_impl<std::tuple_size<T1>::value-1,T1,T2>()(std::forward<F>(f),t1,t2,std::forward<R>(r)));
|
||||
|
||||
/**
|
||||
* filter<int ... I>(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<int pos, int c, int ... I> struct filter_impl;
|
||||
|
||||
// default case where pos != the first I : increase pos
|
||||
template<int pos, int c, int ... I> struct filter_impl : filter_impl<pos+1, c-1, I...> {};
|
||||
|
||||
// when pos == first I
|
||||
template<int pos, int c, int ... I> struct filter_impl<pos, c, pos, I...> {
|
||||
template<typename TupleIn, typename TupleOut> auto operator() (TupleIn const & t, TupleOut && out) const
|
||||
DECL_AND_RETURN( filter_impl<pos+1,c-1, I...>() ( t, push_back(std::forward<TupleOut>(out),std::get<pos>(t))));
|
||||
};
|
||||
|
||||
template<int pos, int ... I> struct filter_impl <pos,-1, I...> {
|
||||
template<typename TupleIn, typename TupleOut> TupleOut operator() (TupleIn const & t, TupleOut && out) const {return out;}
|
||||
};
|
||||
|
||||
template<int ...I, typename Tu>
|
||||
auto filter(Tu const & tu) DECL_AND_RETURN ( filter_impl<0,std::tuple_size<Tu>::value-1, I...>()(tu, std::make_tuple()));
|
||||
|
||||
template<typename Tu,int ...I> struct filter_t_tr : std::result_of< filter_impl<0,std::tuple_size<Tu>::value-1, I...>( Tu, std::tuple<>)>{};
|
||||
|
||||
template<typename Tu,int ...I> using filter_t = typename filter_t_tr<Tu,I...>::type;
|
||||
|
||||
/**
|
||||
* filter_out<int ... I>(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<int pos, int c, int ... I> struct filter_out_impl;
|
||||
|
||||
// default case where pos != the first I : increase pos
|
||||
template<int pos, int c, int ... I> struct filter_out_impl<pos, c, pos, I...> : filter_out_impl<pos+1, c-1, I...> {};
|
||||
|
||||
// when pos == first I
|
||||
template<int pos, int c, int ... I> struct filter_out_impl {
|
||||
template<typename TupleIn, typename TupleOut> auto operator() (TupleIn const & t, TupleOut && out) const
|
||||
DECL_AND_RETURN( filter_out_impl<pos+1,c-1, I...> ()( t, push_back(std::forward<TupleOut>(out),std::get<pos>(t))));
|
||||
};
|
||||
|
||||
template<int pos, int ... I> struct filter_out_impl <pos,-1, I...> {
|
||||
template<typename TupleIn, typename TupleOut> TupleOut operator() (TupleIn const & t, TupleOut && out) const {return out;}
|
||||
};
|
||||
|
||||
template<int ...I, typename Tu>
|
||||
auto filter_out(Tu const & tu) DECL_AND_RETURN ( filter_out_impl<0,std::tuple_size<Tu>::value-1, I...>()(tu, std::make_tuple()));
|
||||
|
||||
template<typename Tu,int ...I> struct filter_out_t_tr : std::result_of< filter_out_impl<0,std::tuple_size<Tu>::value-1, I...>( Tu, std::tuple<>)>{};
|
||||
|
||||
template<typename Tu,int ...I> using filter_out_t = typename filter_out_t_tr<Tu,I...>::type;
|
||||
template <typename T, typename X>
|
||||
auto push_front(T &&t, X &&x) RETURN(std::tuple_cat(std::make_tuple(std::forward<X>(x)), std::forward<T>(t)));
|
||||
|
||||
/// To be rewritten ....
|
||||
/**
|
||||
* inverse_filter<int L, int ... I>(t,x)
|
||||
* Given a tuple t, and integers, returns the tuple R of size L such that filter<I...>(R) == t
|
||||
@ -404,72 +452,45 @@ namespace triqs { namespace tuple {
|
||||
template<int ...I, typename Tu, typename X>
|
||||
auto inverse_filter_out(Tu const & tu, X const &x) DECL_AND_RETURN ( inverse_filter_out_impl<0,0,std::tuple_size<Tu>::value+sizeof...(I)-1, I...>()(tu, std::make_tuple(),x));
|
||||
|
||||
/**
|
||||
* replace<int ... I>(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<int pos, int c, int ... I> struct replace_impl;
|
||||
|
||||
// default case where pos != the first I : increase pos
|
||||
template<int pos, int c, int ... I> struct replace_impl<pos, c, pos, I...> {
|
||||
template<typename TupleIn, typename TupleOut, typename R> auto operator() (TupleIn const & t, TupleOut && out, R const & r) const
|
||||
DECL_AND_RETURN( replace_impl<pos+1,c-1, I...> ()( t, push_back(std::forward<TupleOut>(out),r),r));
|
||||
};
|
||||
|
||||
// when pos == first I
|
||||
template<int pos, int c, int ... I> struct replace_impl {
|
||||
template<typename TupleIn, typename TupleOut, typename R> auto operator() (TupleIn const & t, TupleOut && out, R const & r) const
|
||||
DECL_AND_RETURN( replace_impl<pos+1,c-1, I...> ()( t, push_back(std::forward<TupleOut>(out),std::get<pos>(t)), r));
|
||||
};
|
||||
|
||||
template<int pos, int ... I> struct replace_impl <pos,-1, I...> {
|
||||
template<typename TupleIn, typename TupleOut, typename R> TupleOut operator() (TupleIn const & t, TupleOut && out, R const & r) const {return out;}
|
||||
};
|
||||
|
||||
template<int ...I, typename Tu, typename R>
|
||||
auto replace(Tu const & tu, R const &r) DECL_AND_RETURN ( replace_impl<0,std::tuple_size<Tu>::value-1, I...>()(tu, std::make_tuple(),r));
|
||||
|
||||
|
||||
/*
|
||||
* print a tuple
|
||||
*/
|
||||
template<int a, int b> struct __s {};
|
||||
template<int L, typename T> void print_tuple_impl (std::ostream& os, T const& t, std::integral_constant<int,-1> ) {}
|
||||
template<int L, int rpos, typename T> void print_tuple_impl (std::ostream& os, T const& t, std::integral_constant<int,rpos> ) {
|
||||
os << std::get<L-rpos-1>(t);
|
||||
if (rpos>0) os << ',';
|
||||
print_tuple_impl<L>(os, t, std::integral_constant<int,rpos-1>());
|
||||
* print a tuple
|
||||
*/
|
||||
inline void _triqs_print_tuple_impl(std::ostream &os) {}
|
||||
template <typename T0, typename... T> 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<typename ... T> std::ostream & operator << (std::ostream & os, std::tuple<T...> const & t) {
|
||||
os << "(";
|
||||
constexpr int L = sizeof...(T);
|
||||
triqs::tuple::print_tuple_impl<L>(os,t,std::integral_constant<int,L-1>());
|
||||
return os << ")";
|
||||
template <size_t... Is, typename... T>
|
||||
void _triqs_print_tuple(std::ostream &os, std::tuple<T...> const &t, std14::index_sequence<Is...>) {
|
||||
_triqs_print_tuple_impl(os, std::get<Is>(t)...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace std {
|
||||
|
||||
template <typename... T> std::ostream &operator<<(std::ostream &os, std::tuple<T...> const &t) {
|
||||
os << "(";
|
||||
triqs::tuple::_triqs_print_tuple(os, t, std14::make_index_sequence<sizeof...(T)>());
|
||||
return os << ")";
|
||||
}
|
||||
|
||||
// do not move this up....
|
||||
namespace c14 {
|
||||
|
||||
// a little helper class to wait for the correction that tuple construct is NOT explicit
|
||||
template <typename... Args> class tuple : public std::tuple<Args...> {
|
||||
public:
|
||||
template <typename... Args2> tuple(Args2 &&... args2) : std::tuple<Args...>(std::forward<Args2>(args2)...) {}
|
||||
};
|
||||
}
|
||||
|
||||
// minimal hack to get the metaprogramming work with this tuple too....
|
||||
template <int i, typename... Args>
|
||||
auto get(c14::tuple<Args...> const &t) DECL_AND_RETURN(std::get<i>(static_cast<std::tuple<Args...>>(t)));
|
||||
|
||||
template <typename... Args> class tuple_size<c14::tuple<Args...>> : public tuple_size<std::tuple<Args...>> {};
|
||||
|
||||
// a little helper class to wait for the correction that tuple construct is NOT explicit
|
||||
template <typename... Args> class tuple : public std::tuple<Args...> {
|
||||
public:
|
||||
template <typename... Args2> tuple(Args2 &&... args2) : std::tuple<Args...>(std::forward<Args2>(args2)...) {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
// minimal hack to get the metaprogramming work with this tuple too....
|
||||
template <int i, typename... Args>
|
||||
auto get(c14::tuple<Args...> const &t) DECL_AND_RETURN(std::get<i>(static_cast<std::tuple<Args...>>(t)));
|
||||
|
||||
template <typename... Args> class tuple_size<c14::tuple<Args...>> : public tuple_size<std::tuple<Args...>> {};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user