获取可变参数模板的除最后一个参数之外的所有参数
Obtain all-but-last parameter of variadic template
我有一个这样声明的构造函数:
template<typename... Coords>
MyClass<T>(vector<T> values, Coords... coords) { /* code */ }
我希望它看起来像这样:
template<typename... Coords>
MyClass<T>(Coords... coords, vector<T> values) { /* code */ }
但标准要求可变参数是最后一个。如果我写类似
template<typename... Args>
MyClass<T>(Args... coordsThenValues) { /* code */ }
我如何将 coordsThenValues
拆分为除最后一个参数包 Coords... coords
和最后一个参数 vector<T> values
?
你喜欢元组吗?
你觉得转发元组怎么样?
struct foo {
template<class...Ts>
foo(Ts&&...ts):
foo(
magic<0>{}, // sent it to the right ctor
std::index_sequence< sizeof...(ts)-1 >{}, // the last shall be first
std::make_index_sequence<sizeof...(ts)-1>{}, // the first shall be last
std::forward_as_tuple(std::forward<Ts>(ts)...) // bundled args
)
{}
private:
template<size_t>
struct magic {};
template<size_t...I0s, size_t...I1s, class...Ts>
foo(
magic<0>, // tag
std::index_sequence<I0s...>, // first args
std::index_sequence<I1s...>, // last args
std::tuple<Ts...> args // all args
):
foo(
magic<1>{}, // dispatch to another tagged ctor
std::get<I0s>(std::move(args))..., // get first args
std::get<I1s>(std::move(args))... // and last args
)
{}
// this ctor gets the args in an easier to understand order:
template<class...Coords>
foo(magic<1>, std::vector<T> values, Coords...coords) {
}
};
此处 public 构造函数将参数打包成一个引用元组(可能是 l,可能是 r)。它还得到两组索引。
然后将它发送到 magic<0>
ctor,它会打乱参数,以便最后一个在前面(假设索引是正确的)。
magic<1>
ctor 首先获取向量,然后获取坐标。
基本上我打乱了论点,所以最后一个成为第一个。
magic
的存在只是为了让我不必过多考虑重载决议,并让我明确转发给哪个 ctor。没有它它可能会工作,但我喜欢在使用 ctor 转发做一些疯狂的事情时进行标记。
我有一个这样声明的构造函数:
template<typename... Coords>
MyClass<T>(vector<T> values, Coords... coords) { /* code */ }
我希望它看起来像这样:
template<typename... Coords>
MyClass<T>(Coords... coords, vector<T> values) { /* code */ }
但标准要求可变参数是最后一个。如果我写类似
template<typename... Args>
MyClass<T>(Args... coordsThenValues) { /* code */ }
我如何将 coordsThenValues
拆分为除最后一个参数包 Coords... coords
和最后一个参数 vector<T> values
?
你喜欢元组吗?
你觉得转发元组怎么样?
struct foo {
template<class...Ts>
foo(Ts&&...ts):
foo(
magic<0>{}, // sent it to the right ctor
std::index_sequence< sizeof...(ts)-1 >{}, // the last shall be first
std::make_index_sequence<sizeof...(ts)-1>{}, // the first shall be last
std::forward_as_tuple(std::forward<Ts>(ts)...) // bundled args
)
{}
private:
template<size_t>
struct magic {};
template<size_t...I0s, size_t...I1s, class...Ts>
foo(
magic<0>, // tag
std::index_sequence<I0s...>, // first args
std::index_sequence<I1s...>, // last args
std::tuple<Ts...> args // all args
):
foo(
magic<1>{}, // dispatch to another tagged ctor
std::get<I0s>(std::move(args))..., // get first args
std::get<I1s>(std::move(args))... // and last args
)
{}
// this ctor gets the args in an easier to understand order:
template<class...Coords>
foo(magic<1>, std::vector<T> values, Coords...coords) {
}
};
此处 public 构造函数将参数打包成一个引用元组(可能是 l,可能是 r)。它还得到两组索引。
然后将它发送到 magic<0>
ctor,它会打乱参数,以便最后一个在前面(假设索引是正确的)。
magic<1>
ctor 首先获取向量,然后获取坐标。
基本上我打乱了论点,所以最后一个成为第一个。
magic
的存在只是为了让我不必过多考虑重载决议,并让我明确转发给哪个 ctor。没有它它可能会工作,但我喜欢在使用 ctor 转发做一些疯狂的事情时进行标记。