获取打包中的第N个元素,可以这样写:
选项1
使用tuple_element获取第N个元素的返回类型:
template<size_t index, typename T, typename... Ts>
inline constexpr typename enable_if<index==0, T>::type
get(T&& t, Ts&&... ts) {
return t;
}
template<size_t index, typename T, typename... Ts>
inline constexpr typename enable_if<(index > 0) && index <= sizeof...(Ts),
typename tuple_element<index, tuple<T, Ts...>>::type>::type
get(T&& t, Ts&&... ts) {
return get<index-1>(std::forward<Ts>(ts)...);
}
inline template<long long index, typename... Ts>
constexpr bool index_ok() {
return index >= 0 && index < sizeof...(Ts);
}
template<long long index, typename T, typename... Ts>
inline constexpr
typename enable_if<!index_ok<index, T, Ts...>(), T>::type
get(T&& t, Ts&&... ts) {
static_assert(index_ok<index, T, Ts...>(),
"bad index in call to get, smaller than zero or above pack size");
return t;
}
选项2
不使用 tuple,依赖于 auto 返回类型,具体来说是在 C++14 中使用 decltype(auto),并且将 enable_if 作为模板参数而不是返回类型:
template<size_t index, typename T, typename... Ts,
typename enable_if<index==0>::type* = nullptr>
inline constexpr decltype(auto) get(T&& t, Ts&&... ts) {
return std::forward<T>(t);
}
template<size_t index, typename T, typename... Ts,
typename enable_if<(index > 0 && index <= sizeof...(Ts))>::type* = nullptr>
inline constexpr decltype(auto) get(T&& t, Ts&&... ts) {
return get<index-1>(std::forward<Ts>(ts)...);
}
template<long long index, typename... Ts>
inline constexpr bool index_ok() {
return index >= 0 && index < (long long)sizeof...(Ts);
}
template<long long index, typename T, typename... Ts,
typename enable_if<(!index_ok<index, T, Ts...>())>::type* = nullptr>
inline constexpr decltype(auto) get(T&& t, Ts&&... ts) {
static_assert(index_ok<index, T, Ts...>(),
"bad index in call to get, smaller than zero or above pack size");
return std::forward<T>(t);
}
使用示例:
template<size_t index, typename... Ts>
void resetElementN(Ts&&... ts) {
get<index>(std::forward<Ts>(ts)...) = {};
}
int main() {
int i = 0;
string s = "hello";
get<0>(i,2,"hello","hello"s, 'a') += get<0>(2);
get<1>(1,i,"hello",4) += get<1>(1, 2);
get<3>(1,2,"hello",i) += get<2>(0, 1, 2);
get<2>(1,2,s,4) = get<2>(0, 1, "hi");
cout << i << ' ' << s << endl;
resetElementN<1>(0, i, 2);
resetElementN<0>(s, 1, 2);
cout << i << ' ' << s << endl;
const int j = 2;
cout << get<0>(j,i,3,4) << endl;
}
代码
选项 1:
http://coliru.stacked-crooked.com/a/60ad3d860aa94453
选项 2:
http://coliru.stacked-crooked.com/a/09f6e8e155612f8b
std::tuple
中,并使用std::get
和std::tuple_element
,这些都是递归实现的。还可以参考此答案。 - dypstd::get
和std::tuple_element
并不一定需要递归实现,它们可以通过索引、重载解析和派生到基类的转换来实现而不需要递归。 - Xeostd::tuple_element<...>
,这将是递归函数。 - Dietmar Kühlstd::tuple_element
的类型推导和索引 -- 但是索引需要递归(或手动)创建。 - dyp