Sim*_*ten 3 c++ visual-c++ c++11 c++14
正如标题所说,我有一个Variadic模板,至少可以接受3个参数(int's)
template<int p_first, int p_second, int p_third, int... p_rest>
Run Code Online (Sandbox Code Playgroud)
我需要将它们分成第一个,中间一个和最后一个
class MyClass {
OtherClass<p_first> first;
// Works obviously
// std::vector<OtherClass> middle... Doesn't work
OtherClass<p_last> last;
// No idea how to do this
}
Run Code Online (Sandbox Code Playgroud)
Visual Studio 2015 C++功能可用
编辑:对不起,我忘了提到关键方面.
OtherClass实现:
template <int v>
class OtherClass { ... };
Run Code Online (Sandbox Code Playgroud)是的,我想要中间的所有值(在第一个和最后一个之间)
谢谢你的帖子.我明白了,测试代码并尽快评论!
你可以写一个辅助结构,以获得N
日int
从int
包:
template <std::size_t N, int... I>
struct get_n :
std::integral_constant<int,
std::get<N>(std::array<int,sizeof...(I)> { I... })
>
{};
Run Code Online (Sandbox Code Playgroud)
然后你可以编写元函数来获得中间和结尾:
template <int... I>
using get_middle = get_n<sizeof...(I)/2 - 1, I...>;
template <int... I>
using get_end = get_n<sizeof...(I) - 1, I...>;
Run Code Online (Sandbox Code Playgroud)
您可以这样使用:
using p_last = get_end<p_third, p_rest...>;
OtherClass<p_last> last;
Run Code Online (Sandbox Code Playgroud)
如果你想要一个OtherClass<N>
所有中间元素的元组,这是一个相当简单的解决方案.请参阅Yakk的答案,了解更复杂,更灵活的答案.
template <template <int> class ToBuild, class Seq, int... Args>
struct build_tuple;
template <template <int> class ToBuild, std::size_t... Idx, int... Args>
struct build_tuple<ToBuild, std::index_sequence<Idx...>, Args...> {
using type = std::tuple<ToBuild<get_n<Idx, Args...>::value>...>;
};
template<int p_first, int p_second, int p_third, int... p_rest>
struct MyClass {
MyClass() {
typename build_tuple<OtherClass,
std::make_index_sequence<sizeof...(p_rest) + 1>,
p_second, p_third, p_rest...>::type middle;
}
};
Run Code Online (Sandbox Code Playgroud)
首先,样板.我在类型而不是常量中工作,因为使用类型进行元编程要容易得多.
template<class T>struct tag{using type=T;};
template<class Tag>using type_t=typename Tag::type;
template<int I>using int_k=std::integral_constant<int, I>;
template<class...>struct types{using type=types;};
template<template<class...>class Z, class pack>
struct apply;
template<template<class...>class Z, class pack>
using apply_t=type_t<apply<Z,pack>>;
template<template<class...>class Z, class...Ts>
struct apply<Z, types<Ts...>>:tag<Z<Ts...>>{};
Run Code Online (Sandbox Code Playgroud)
现在,一旦我们有一组中间元素,我们就可以应用它们.
template <std::size_t N, class... Ts>
using get_t = type_t< std::tuple_element< N, std::tuple<Ts...> > >;
Run Code Online (Sandbox Code Playgroud)
从类型列表中获取第n个类型.
template <class Is, class pack>
struct get_slice;
template <class Is, class pack>
using get_slice_t=type_t<get_slice<Is,pack>>;
template<std::size_t...Is, class...Ts>
struct get_slice<std::index_sequence<Is...>,types<Ts...>>:
types< get_t<Is, Ts...>... >{};
Run Code Online (Sandbox Code Playgroud)
这让我们可以拿出一个包,从中获取一个切片.
偏移索引序列:
template<class Is, std::size_t I>
struct offset;
template<class Is, std::size_t I>
using offset_t=type_t<offset<Is,I>>;
template<std::size_t...Is, size_t I>
struct offset<std::index_sequence<Is...>, I>:
tag<std::index_sequence<(I+Is)...>>
{};
Run Code Online (Sandbox Code Playgroud)
从长度len开始提取中间元素:
template<std::size_t start, std::size_t len, class pack>
struct get_mid:
get_slice< offset_t< std::make_index_sequence<len>, start >, pack >
{};
template<std::size_t start, std::size_t len, class pack>
using get_mid_t=type_t<get_mid<start,len,pack>>;
Run Code Online (Sandbox Code Playgroud)
现在我们可以将你的元素分成第一个,最后一个,并将其余部分放在一个元组中:
template<int p_first, int p_second, int p_third, int...is>
class MyClass {
using pack = types< int_k<p_first>, int_k<p_second>, int_k<p_third>, int_k<is>... >;
OtherClass<p_first> first;
using mid = get_mid_t<1, sizeof...(is)+1, pack >;
template<class...Ts>
using OtherClass_tuple = std::tuple<OtherClass<Ts::value>...>;
apply_t< OtherClass_tuple, mid > middle;
OtherClass<get_t<sizeof...(is)+2, pack>::value> last;
};
Run Code Online (Sandbox Code Playgroud)