We can implement a simple function to get nth parameter directly without any recursive calls but many pure type operations in compile-time.
Let's look at the key code firstly:
template<class...Ts>
struct GetImp {
  template<class T, class...Us>
  static decltype(auto) impl(Ts&&..., T&& obj, Us&&...) {
    return std::forward<T>(obj);
  }
};
template<size_t n, class...Ts>
decltype(auto) get(Ts&&...args) {
  static_assert(n<sizeof...(args), "index over range");
  return Transform<GetImp, Before_s<n, Seq<Ts...>> >
    ::impl(std::forward<Ts>(args)...);
}
What does Transform means?
For example, if we have a type T that is std::tuple<int,double,float>,
then Transform<GetImp,T> would be GetImp<int,double,float>.
note that I define another empty struct "Seq" instead of std::tuple to do
the same thing with less compile time.(In fact both of them could be compiled very quickly,but I guess an empty struct would be more effectively) 
So Before_s<n,Seq<Ts...>> generate a Seq<?> and then we transform it into GetImp, so that we can know what type of [0]~[n-1] parameters are,
and then drop them off to index the nth parameter directly.
For example, Before_s<3,Seq<T0,T1,T2,T3,T4...>> is Seq<T0,T1,T2>,
Before_s<2,Seq<T0,T1,T2,T3,T4...>> is Seq<T0,T1> etc.
We use Before_s to deal with our Seq type to reduce compile time when we
use one meta function to implement another meta function for less compile
time.
Implementation
#define OMIT_T(...) typename __VA_ARGS__::type
template<class...Args>
struct Seq { };
template< template<class...> class Dst >
struct TransformImp{
    template< template<class...>class Src, class...Args >
    static Dst<Args...> from(Src<Args...>&&);
};
template< template<class...> class Dst, class T>
using Transform = decltype(TransformImp<Dst>::from(std::declval<T>()));
template<class T>
using Seqfy = Transform<Seq, T>;
template<class...>struct MergeImp;
template<class...Ts, class...Others>
struct MergeImp<Seq<Ts...>, Seq<Others...>>
{
  using type = Seq<Ts..., Others...>;
};
template<class first, class second>
using Merge = OMIT_T(MergeImp<Seqfy<first>, Seqfy<second> >);
template<class T, class U>
using Merge_s = OMIT_T(MergeImp<T, U>);
template<size_t, class...>struct BeforeImp;
template<size_t n, class T, class...Ts>
struct BeforeImp<n, Seq<T, Ts...>> {
    static_assert(n <= sizeof...(Ts)+1, "index over range");
    using type = Merge_s<Seq<T>, OMIT_T(BeforeImp<n - 1, Seq<Ts...>>)>;
};
template<class T, class...Ts>
struct BeforeImp<1, Seq<T, Ts...>> {
    using type = Seq<T>;
};
template<class T, class...Ts>
struct BeforeImp<0, Seq<T, Ts...>> {
    using type = Seq<>;
};
template<size_t n>
struct BeforeImp<n, Seq<>> {
    using type = Seq<>;
};
template<size_t n, class T>
using Before = OMIT_T(BeforeImp<n, Seqfy<T>>);
template<size_t n, class T>
using Before_s = OMIT_T(BeforeImp<n, T>);
Edited: Advanced Implementation
We needn't use Before_s to calculate n-1 types before nth type,instead,
we can ignore them:
struct EatParam{
    constexpr EatParam(...)noexcept{}
};
template<size_t n>
struct GenSeqImp {
  using type = Merge_s<OMIT_T(GenSeqImp<n / 2>), OMIT_T(GenSeqImp<n - n / 2>)>;
};
template<>
struct GenSeqImp<0> {
  using type = Seq<>;
};
template<>
struct GenSeqImp<1> {
  using type = Seq<EatParam>;
};
template<size_t n>
using GenSeq = OMIT_T(GenSeqImp<n>);
template<class...Ts>
struct GetImp {
  template<class T>
  static constexpr decltype(auto) impl(Ts&&..., T&& obj, ...)noexcept {
    return std::forward<T>(obj);
  }
};
template<size_t n, class...Ts>
constexpr decltype(auto) get(Ts&&...args)noexcept {
  static_assert(n<sizeof...(args), "index over range.");
  //return Transform<GetImp, Before_s<n, Seq<Ts...>> >
  return Transform<GetImp, GenSeq<n>>
    ::impl(std::forward<Ts>(args)...);
}
In addition , there is a very interesting article about implementation of getting nth type:
Thanks for their work, I didn't know we could use (...) to do the hack before.