K-b*_*llo 4 c++ templates std c++11
我试图分index_sequence成两半.为此,我index_sequence使用下半部分生成一个并使用它来跳过完整的前导元素index_sequence.以下是一个最小的测试用例,代表了我正在努力实现的目标:
template <int ...I>
struct index_sequence {};
template <int ...I, int ...J>
void foo(index_sequence<I...>, index_sequence<I..., J...>)
{}
int main()
{
foo(index_sequence<0>{}, index_sequence<0, 1>{});
}
Run Code Online (Sandbox Code Playgroud)
我用最新版本的Clang,GCC和MSVC试过这个,但它们都没有推断出来J....标准是否允许这样做?如果没有,为什么以及什么是实现我的意图的好方法?
14.8.2.5/9 ...如果模板参数列表
P包含的包扩展不是最后一个模板参数,则整个模板参数列表是非推导的上下文...
因此,在index_sequence<I..., J...>与之比较时index_sequence<0, 1>{},既I...不能J...也不能推断.
如果你想要的是拆分std::index_sequence而不是删除两个公共前缀std::index_sequence,我认为你可以从一个实现中受益slice并使用它来分割std::index_sequence成碎片.
我将省略std::index_sequence和朋友的实现,因为你可以参考文章,N3658,以及这里的示例实现.
为了实现slice,我们将使用一个名为的帮助器make_integer_range.我们想要一个std::index_sequence生成器,它给我们[Begin,End]而不是[0,End].利用std::make_integer_sequence,我们得到:
template <typename T, typename Seq, T Begin>
struct make_integer_range_impl;
template <typename T, T... Ints, T Begin>
struct make_integer_range_impl<T, std::integer_sequence<T, Ints...>, Begin> {
using type = std::integer_sequence<T, Begin + Ints...>;
};
/* Similar to std::make_integer_sequence<>, except it goes from [Begin, End)
instead of [0, End). */
template <typename T, T Begin, T End>
using make_integer_range = typename make_integer_range_impl<
T, std::make_integer_sequence<T, End - Begin>, Begin>::type;
/* Similar to std::make_index_sequence<>, except it goes from [Begin, End)
instead of [0, End). */
template <std::size_t Begin, std::size_t End>
using make_index_range = make_integer_range<std::size_t, Begin, End>;
Run Code Online (Sandbox Code Playgroud)
由于我们没有类似std::get的功能std::index_sequence或可变参数模板包,我们只是构建一个临时的std::array来获取我们std::get.然后只使用我们想要的切片来爆炸数组.
template <std::size_t... Indices, std::size_t... I>
constexpr decltype(auto) slice_impl(
std::index_sequence<Indices...>,
std::index_sequence<I...>) {
using Array = std::array<std::size_t, sizeof...(Indices)>;
return std::index_sequence<std::get<I>(Array{{Indices...}})...>();
}
template <std::size_t Begin, std::size_t End, std::size_t... Indices>
constexpr decltype(auto) slice(std::index_sequence<Indices...> idx_seq) {
return slice_impl(idx_seq, make_index_range<Begin, End>());
}
Run Code Online (Sandbox Code Playgroud)
使用slice我们刚刚构建的一个例子是编写一个split_at函数.我们指定要分割的索引std::index_sequence,并std::index_sequence在给定索引处返回一对s split.
template <std::size_t At, std::size_t... Indices>
constexpr decltype(auto) split_at(index_sequence<Indices...> idx_seq) {
return std::make_pair(slice<0, At>(idx_seq),
slice<At, sizeof...(Indices)>(idx_seq));
}
Run Code Online (Sandbox Code Playgroud)
split_at:static_assert(std::is_same<
decltype(split_at<2>(index_sequence<1, 4, 2>())),
std::pair<index_sequence<1, 4>, index_sequence<2>>>(), "");
static_assert(std::is_same<
decltype(split_at<1>(index_sequence<1, 4, 2, 3>())),
std::pair<index_sequence<1>, index_sequence<4, 2, 3>>>(), "");
Run Code Online (Sandbox Code Playgroud)