#ifndef ETOEX_TUPLE_H_
#define ETOEX_TUPLE_H_

#include <tuple>

namespace Tuple
{
  template <typename RetT, typename ...Args>
  struct TupleBind
  {
    RetT(*func)(Args...);
    std::tuple<Args...> params;

    TupleBind(RetT(*f)(Args...), std::tuple<Args...> par)
      :
      func{ f },
      params{ par } 
    {}

    RetT delayed_dispatch()
    {
      return callFunc(std::index_sequence_for<Args...>{});
    }

    template<std::size_t... Is>
    RetT callFunc(std::index_sequence<Is...>)
    {
      return func(std::get<Is>(params) ...);
    }
  };

  template<int... Is>
  struct seq { };

  template<int N, int... Is>
  struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };

  template<int... Is>
  struct gen_seq<0, Is...> : seq<Is...> { };

  template<typename... Args, int... Is>
  auto make_pointer_tuple(std::tuple<Args...>& t, seq<Is...>)
    -> std::tuple<typename std::add_pointer<Args>::type...>
  {
    return std::make_tuple(&std::get<Is>(t)...);
  }

  template<typename... Args>
  auto make_pointer_tuple(std::tuple<Args...>& t)
    -> std::tuple<typename std::add_pointer<Args>::type...>
  {
    std::tuple<Args...> cpp_args;
    return make_pointer_tuple(t, gen_seq<sizeof...(Args)>());
  }


};

#endif