4

在 move.h 中,有两个重载forward

template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type& __t) noexcept
{
    return static_cast<_Tp&&>(__t);
}

template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
{
    static_assert(
        !std::is_lvalue_reference<_Tp>::value,
        "template argument substituting _Tp is an lvalue reference type"
    );
    return static_cast<_Tp&&>(__t);
}

我看到这static_assert是为了防止意外地将右值转换为左值。右值版本可以这样实现吗:

template<typename _Tp>
typename std::remove_reference<_Tp>::type&&         
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
{
    return __t;
}
4

2 回答 2

6

它可以防止奇怪的事情,例如std::forward<std::string&>(std::string {}).

该行为由 §20.2.3p2 规定:

如果第二种形式是用左值引用类型实例化的,则程序是非良构的。

于 2012-04-26T15:01:36.920 回答
6

例如,为什么将右值作为左值转发是危险的,请参见N2951的用例C。这个用例展示了这样做如何使创建悬空引用变得容易。

于 2012-04-26T15:12:11.773 回答