【问题标题】:std::get does not forward rvalue-reference for std::applystd::get 不转发 std::apply 的右值引用
【发布时间】:2020-01-03 13:04:06
【问题描述】:

我想知道为什么std::apply 在处理元组中的引用类型时不转发rvalue-reference(请参阅Live):

#include <type_traits>
#include <tuple>

template<typename T>
void assertRvalueReference(T&& t)
{   
    static_assert(std::is_rvalue_reference_v<decltype(t)>, "Ups"); 
}

int main()
{
    struct A{};
    A a;
    int v;
    auto t = std::tuple<A&&, int>(std::move(a), v); // essentially `std::forward_as_tuple(v, std::move(a))`

    std::apply([](auto&& arg, ...)
               {
                   assertRvalueReference(std::forward<decltype(arg)>(arg)); 
               }, std::move(t));

    std::apply([](auto&& arg, ...)
               {
                   // assertRvalueReference(arg); // This should in my opinion not fail
               }, t);

    assertRvalueReference(non_std_get<0>(t)); 
}

根本原因是std::get 和引用折叠规则。 如果std::apply 在内部使用这个non_std_get 会不会更有意义


template<std::size_t Index, typename Tuple>
constexpr decltype(auto) non_std_get(Tuple&& t)
{
    using Type = std::tuple_element_t<Index, std::remove_cvref_t<Tuple>>;
    if constexpr(std::is_rvalue_reference_v<Type>)
    {
        return std::move(std::get<Index>(t));
    }
    else
    {
        return std::get<Index>(t);
    }
}

这将是一个完美的前锋

std::apply([](auto&& arg){/*arg is here `int&&`*/}, t);

【问题讨论】:

  • 一个 rrvalue--reference 是一个左值。在这种特定情况下使其行为不同会令人困惑。
  • 那是真的,但是 std::apply(t,...) int a; auto t = std::forward_as_tuple(a, A{}) 在没有做完美前锋时有什么用处,这意味着 lambda 应该得到一个 rvalue-reference = A&amp;&amp; (它没有,它得到一个 @ 987654333@)
  • 这对我来说很有意义,因为将右值引用传递给函数实际上是将左值传递给函数。我不希望代码在没有我告诉它这样做的情况下神奇地为我做隐藏的事情。在这种情况下,我希望 apply_with_forwarding 能够在我的代码中明确显示。

标签: c++ c++17 rvalue-reference stdtuple stdapply


【解决方案1】:

问题不在于std::apply,而在于您的 lambda。

在您的 lambda 中,arg始终是一个左值。您需要使用std::forward 将其显式转换为右值才能使其成为右值。

【讨论】:

  • 您的陈述对我来说很清楚,真正的问题在于std::get,如果 lvalue 元组包含类型 A&amp;&amp; = rvalue-reference,它会返回 A&amp; .
猜你喜欢
  • 1970-01-01
  • 2020-07-07
  • 2016-04-24
  • 1970-01-01
  • 2021-08-26
  • 2015-07-15
  • 1970-01-01
  • 1970-01-01
  • 2021-10-10
相关资源
最近更新 更多