Hi during my implementation of unique_ptr I noticed that boost::forward
doesn't play nicely with lvalue ref types.
int a;
int &b = a;
int &c = std::forward(b); // compiles fine
int &d = boost::forward(b); // compiler error
I did a little playing around with the declarations of forward and I managed
to get this to work:
// if T is not a lvalue ref and movable
template <class T>
inline typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value &&
::boost::move_detail::is_rv<T>::value &&
!::boost::move_detail::is_lvalue_reference<T>::value, const T &>::type
forward(typename ::boost::move_detail::identity<T>::type &x)
BOOST_NOEXCEPT
{
return const_cast(x);
}
// if T is not a lvalue ref and not movable
template <class T>
inline typename ::boost::move_detail::enable_if_c
< enable_move_utility_emulation<T>::value &&
!::boost::move_detail::is_rv<T>::value &&
!::boost::move_detail::is_lvalue_reference<T>::value, const T
&>::type
forward(const typename ::boost::move_detail::identity<T>::type &x)
BOOST_NOEXCEPT
{
return x;
}
// if T is a lvalue ref
template <class T>
inline typename ::boost::move_detail::enable_if_c
< ::boost::move_detail::is_lvalue_reference<T>::value , T>::type
forward(T x) BOOST_NOEXCEPT
{
return x;
}
Basically, this forces all calls to forward to simply return the lvalue
ref (const-ness is maintained, I think), otherwise it does whatever
boost::forward did before.
As far as I can tell, this doesn't break boost::forward, and it enables it
to properly handle taking lvalue refs. Am I right in my assumptions? Are
there any cases where this would fail to produce standard-compliant/desired
results?