模板元编程:如何将参数包组合成新的参数包
Template Meta Programming: How to combine parameter packs to new parameter pack
我正在尝试实现一种从元组中删除某些类型的方法;例如,我希望能够根据条件只取元组的前 2 个模板参数的元组:
- 是否可以'pack'元组的类型返回参数包? (元组 -> 类型名... contained_types)
- 是否可以组合参数。用类型名打包(例如使用 "Pack1..., Pack2..." 为结构指定单个参数包?
#include <cstdint>
#include <tuple>
template <typename... tpl> struct Helper {
template <std::size_t rem, typename curr, typename... rest> struct take {
using type = Helper<(tpl..., curr)>::take<rem-1, rest...>::type; // here, I'm trying (2.)
};
template <typename curr, typename... rest> struct take<0, curr, rest...> {
using type = std::tuple<tpl...>;
};
};
template <std::size_t s, typename... tpl> using take_t = Helper<>::take<s, tpl...>;
int main() {
take_t<2, int, int, int> k = std::make_tuple(1, 2);
}
编辑 Helper 行失败并显示以下消息:
/home/juli/test.cc:6:18: error: need ‘typename’ before ‘Helper<tpl ..., curr>::take’ because ‘Helper<tpl ..., curr>’ is a dependent scope
6 | using type = Helper<tpl..., curr>::take<rem-1, rest...>::type;
当我提供类型名称时
/home/juli/test.cc:6:53: error: expected ‘;’ before ‘<’ token
6 | using type = typename Helper<tpl..., curr>::take<rem-1, rest...>::type;
edit2
我通过 [helper functions](https://gist.github.com/juliusHuelsmann/669f537aeb5e7105386d510d186b24e1
),但是当构造函数不是 constexpr 时,那些非基本类型会失败,所以我不能在我的用例中使用它,并且很想知道如何实现这一点以及我的方法失败的原因。
问题 2 的答案)
是的,正如@user253751 所建议的那样,我原来的方法 (Helper<tpl..., curr>
) 是正确的,但我犯了一个不同的错误,这导致了该行中的上述错误,因为在使用的类型之后省略了 'template'。
下面的代码显示了修复并且工作正常:
#include <cstdint>
#include <tuple>
template <typename... tpl> struct Helper {
template <std::size_t rem, typename curr, typename... rest> struct take {
using tp = Helper<tpl..., curr>;
using type = tp::template take<rem-1, rest...>::type;
};
template <typename curr, typename... rest> struct take<0, curr, rest...> {
using type = std::tuple<tpl...>;
};
};
template <std::size_t s, typename... tpl> using take_t = Helper<>::take<s, tpl...>;
int main() {
take_t<2, int, int, int>::type k = std::make_tuple(1, 2);
}
问题 1 的答案由执行的技巧 here, see a full example here 给出。这是可能的,例如通过以下构造(改编自即时且未经测试的示例):
template <class tuple> struct foo;
template <class ... args> struct foo<std::tuple<args...> {
// implementation here!
};
这非常简洁,也可以用于 integer_sequence(我尝试过但直到现在才成功)。
我想要实现的完整实现比我上面的初始方法更清晰here:
template <size_t s, typename is, typename ...args> struct thlp;
template <size_t s, size_t... i, class... args> struct thlp<s, std::index_sequence<i...>, args...> {
static_assert(s <= sizeof...(args), "Requested new tuple size exceeds old one.");
using type = std::tuple<std::tuple_element_t<i, std::tuple<args...>>...>;
};
template <size_t s, typename... args>
using conditional_tuple_t = thlp<s, decltype(std::make_index_sequence<s>()), args...>::type;
我正在尝试实现一种从元组中删除某些类型的方法;例如,我希望能够根据条件只取元组的前 2 个模板参数的元组:
- 是否可以'pack'元组的类型返回参数包? (元组 -> 类型名... contained_types)
- 是否可以组合参数。用类型名打包(例如使用 "Pack1..., Pack2..." 为结构指定单个参数包?
#include <cstdint>
#include <tuple>
template <typename... tpl> struct Helper {
template <std::size_t rem, typename curr, typename... rest> struct take {
using type = Helper<(tpl..., curr)>::take<rem-1, rest...>::type; // here, I'm trying (2.)
};
template <typename curr, typename... rest> struct take<0, curr, rest...> {
using type = std::tuple<tpl...>;
};
};
template <std::size_t s, typename... tpl> using take_t = Helper<>::take<s, tpl...>;
int main() {
take_t<2, int, int, int> k = std::make_tuple(1, 2);
}
编辑 Helper 行失败并显示以下消息:
/home/juli/test.cc:6:18: error: need ‘typename’ before ‘Helper<tpl ..., curr>::take’ because ‘Helper<tpl ..., curr>’ is a dependent scope
6 | using type = Helper<tpl..., curr>::take<rem-1, rest...>::type;
当我提供类型名称时
/home/juli/test.cc:6:53: error: expected ‘;’ before ‘<’ token
6 | using type = typename Helper<tpl..., curr>::take<rem-1, rest...>::type;
edit2 我通过 [helper functions](https://gist.github.com/juliusHuelsmann/669f537aeb5e7105386d510d186b24e1 ),但是当构造函数不是 constexpr 时,那些非基本类型会失败,所以我不能在我的用例中使用它,并且很想知道如何实现这一点以及我的方法失败的原因。
问题 2 的答案)
是的,正如@user253751 所建议的那样,我原来的方法 (Helper<tpl..., curr>
) 是正确的,但我犯了一个不同的错误,这导致了该行中的上述错误,因为在使用的类型之后省略了 'template'。
下面的代码显示了修复并且工作正常:
#include <cstdint>
#include <tuple>
template <typename... tpl> struct Helper {
template <std::size_t rem, typename curr, typename... rest> struct take {
using tp = Helper<tpl..., curr>;
using type = tp::template take<rem-1, rest...>::type;
};
template <typename curr, typename... rest> struct take<0, curr, rest...> {
using type = std::tuple<tpl...>;
};
};
template <std::size_t s, typename... tpl> using take_t = Helper<>::take<s, tpl...>;
int main() {
take_t<2, int, int, int>::type k = std::make_tuple(1, 2);
}
问题 1 的答案由执行的技巧 here, see a full example here 给出。这是可能的,例如通过以下构造(改编自即时且未经测试的示例):
template <class tuple> struct foo;
template <class ... args> struct foo<std::tuple<args...> {
// implementation here!
};
这非常简洁,也可以用于 integer_sequence(我尝试过但直到现在才成功)。
我想要实现的完整实现比我上面的初始方法更清晰here:
template <size_t s, typename is, typename ...args> struct thlp;
template <size_t s, size_t... i, class... args> struct thlp<s, std::index_sequence<i...>, args...> {
static_assert(s <= sizeof...(args), "Requested new tuple size exceeds old one.");
using type = std::tuple<std::tuple_element_t<i, std::tuple<args...>>...>;
};
template <size_t s, typename... args>
using conditional_tuple_t = thlp<s, decltype(std::make_index_sequence<s>()), args...>::type;