取可变参数模板参数的尾部
Take tail of variadic template parameters
给定此类型:
template<typename ...As>
struct Base {};
我需要实现一个函数
template<int i, typename ...As>
constexpr auto Tail() {
static_assert(i < sizeof...(As), "index out of range");
return ??;
}
它使用索引 i
中的类型参数列表的尾部返回B
实例。
例如
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
我知道如何在索引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;
};
但我无法获得整个问题的工作版本。
如果您不介意使用 C++17。甚至不需要static_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>();
}
顺便说一句,将int
更改为unsigned
以避免负数(几乎(无限递归的可能性。
对于Tail
(为什么它是一个函数?(,该方法几乎可以与type_at
相同。您唯一需要更改的是递归的基本情况:
template <typename ... Ts>
struct types_from<0, Ts...> {
using type = Base<Ts...>; // we don't like nasty typedef syntax
};
而现在,对于完全不同的东西...
只是为了好玩,我提出了一个 C++14 解决方案,它不使用递归,而是使用std::tuple_cat()
的力量。
#include <tuple>
#include <type_traits>
template <typename...>
struct Base
{ };
template <std::size_t I, std::size_t J, typename A,
std::enable_if_t<(I <= J), bool> = true>
constexpr std::tuple<Base<A>> Tail_helper3 ();
template <std::size_t I, std::size_t J, typename A,
std::enable_if_t<(I > J), bool> = true>
constexpr std::tuple<> Tail_helper3 ();
template <typename ... As>
constexpr Base<As...> Tail_helper2 (std::tuple<Base<As>...> const &);
template <std::size_t I, typename ... As, std::size_t ... Is>
constexpr auto Tail_helper1 (std::index_sequence<Is...> const &)
-> decltype( Tail_helper2(std::tuple_cat(Tail_helper3<I, Is, As>()...)) );
template <std::size_t I, typename ... As>
constexpr auto Tail ()
-> decltype( Tail_helper1<I, As...>(std::index_sequence_for<As...>{}) )
{
static_assert(I < sizeof...(As), "index out of range");
return {};
}
int main ()
{
static_assert( std::is_same_v<Base<int, double, int>,
decltype(Tail<0u, int, double, int>())> );
static_assert( std::is_same_v<Base<double, int>,
decltype(Tail<1u, int, double, int>())> );
static_assert( std::is_same_v<Base<int>,
decltype(Tail<2u, int, double, int>())> );
// Tail<3u, int, double, int>(); compilation error!
}
相关文章:
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 视图中的参数推导失败:take_while
- 取可变参数模板参数的尾部
- 为什么后缀失败并且前缀在传递迭代器作为参数并在尾部位置递归时工作正常
- VS2012-在尾部返回类型中将类型声明为模板参数
- 我如何从尾部而不是头部拉出可变模板参数