作者热门文章
- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
考虑 std::apply
的可能实现:
namespace detail {
template <class F, class Tuple, std::size_t... I>
constexpr decltype(auto) apply_impl(F &&f, Tuple &&t, std::index_sequence<I...>)
{
return std::invoke(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...);
}
} // namespace detail
template <class F, class Tuple>
constexpr decltype(auto) apply(F &&f, Tuple &&t)
{
return detail::apply_impl(
std::forward<F>(f), std::forward<Tuple>(t),
std::make_index_sequence<std::tuple_size_v<std::decay_t<Tuple>>>{});
}
为什么调用函数(f
)时我们不需要执行 t
参数元组传递(std::forward
)在元组的每个元素上 std::get<I>(std::forward<Tuple>(t))...
在实现中?
最佳答案
你不需要 std::forward
每个元素因为 std::get
为元组的右值引用和左值引用重载。
std::forward<Tuple>(t)
会给你一个左值( Tuple &
)或一个右值( Tuple &&
),并且取决于你得到什么, std::get
会给你一个T &
(左值)或 T &&
(右值)。查看 std::get
的各种重载.
关于 std::tuple
的一些细节和 std::get
-
如 StoryTeller 所述,元组的每个成员都是左值,无论它是从右值还是左值构造的,在这里都无关紧要:
double a{0.0};
auto t1 = std::make_tuple(int(), a);
auto t2 = std::make_tuple(int(), double());
问题是——元组是右值吗?如果是,你可以移动它的成员,如果不是,你必须做一个拷贝,但是std::get
已经通过返回具有相应类别的成员来解决这个问题。
decltype(auto) a1 = std::get<0>(t1);
decltype(auto) a2 = std::get<0>(std::move(t1));
static_assert(std::is_same<decltype(a1), int&>{}, "");
static_assert(std::is_same<decltype(a2), int&&>{}, "");
回到一个具体的例子 std::forward
:
template <typename Tuple>
void f(Tuple &&tuple) { // tuple is a forwarding reference
decltype(auto) a = std::get<0>(std::forward<Tuple>(tuple));
}
f(std::make_tuple(int())); // Call f<std::tuple<int>>(std::tuple<int>&&);
std::tuple<int> t1;
f(t1); // Call f<std::tuple<int>&>(std::tuple<int>&);
在第一次调用f
, a
的类型将是 int&&
因为tuple
将作为 std::tuple<int>&&
转发,而在第二种情况下,它的类型将是 int&
因为tuple
将作为 std::tuple<int>&
转发.
关于c++ - std::apply forward parameters 如何在没有显式 std::forward 的情况下应用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41260680/
我是一名优秀的程序员,十分优秀!