取可变参数模板参数的尾部

Reg*_*lez 5 c++ template-meta-programming variadic-templates

给定此类型:

template<typename ...As>
struct Base {};
Run Code Online (Sandbox Code Playgroud)

我需要实现一个功能

template<int i, typename ...As>
constexpr auto Tail() {
   static_assert(i < sizeof...(As), "index out of range");
   return ??;
}
Run Code Online (Sandbox Code Playgroud)

它返回一个B使用index中的类型参数列表尾部的实例i

例如,

Tail<0, int, float, double>() -> Base<int, float, double>
Tail<1, int, float, double>() -> Base<float, double>
Tail<2, int, float, double>() -> Base<double>
Tail<3, int, float, double>() -> fails with static assert
Run Code Online (Sandbox Code Playgroud)

我知道如何在索引处获取类型i

template <int64_t i, typename T, typename... Ts>
struct type_at
{
    static_assert(i < sizeof...(Ts) + 1, "index out of range");
    typedef typename type_at<i - 1, Ts...>::type type;
};

template <typename T, typename... Ts> struct type_at<0, T, Ts...> {
    typedef T type;
};
Run Code Online (Sandbox Code Playgroud)

但是我无法获得整个问题的有效版本。

bar*_*top 4

如果您不介意使用 C++17。Evenstatic_assert是不需要的:

template<unsigned i, typename T, typename ...Ts>
constexpr auto Tail() {
    if constexpr (i == 0)
        return Base<T, Ts...>();
    else 
        return Tail<i - 1, Ts...>();
}


int main(){
    Base<int, double, int> a = Tail<0, int, double, int>();    
    Base<double, int> b = Tail<1, int, double, int>();
    Base<int> c = Tail<2, int, double, int>();
    auto d = Tail<3, int, double, int>();
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,更改intunsigned以避免负数(几乎)无限递归的可能性。