Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why there is no std::move_if_noexcept counterpart for std::forward in C++11/14?

I have watched Scott Meyers' talk on GoingNative2013 "An Effective C++11/14 Sampler" and he explained the use of std::move_if_noexcept.

So in my opinion there should be a std::forward_if_noexcept to also guarantee exception-safety for forward? Why is there nothing like this in the Standard Library? Is there another possibility to guarantee it?

like image 678
Benjamin Schmidt Avatar asked Aug 15 '14 19:08

Benjamin Schmidt


1 Answers

The forward semantics already are conditional, i.e., they preserve the value category of its argument. The move, on the other hand, unconditionally changes (from an l-value to r-value) the value category of its argument to an r-value (reference), the std::move_if_noexcept obtains the resultant value category based on whether or not the move constructor throws no exceptions, effectively also making it conditional.

In short, std::forward doesn't change anything, it preserves the value category. std::move on the other hand, does change the value category. So std::move_if_noexcept is introduced to say that if std::move's change could cause an exception, then don't change anything; don't move it.

I think the rationale here also goes to the intended idiomatic use of all things std::move and std::forward respectively. In one of Scott's other talks (possibly at C++ and Beyond 2012) on "universal references", forwarding and moving, he was quite emphatic on the idiomatic use of forward, and I think this underpins a lot of what std::forward is and how it is used. It may also just be as simple as it was never considered.

I would argue that there is no need, or at least there is diminished need when the std::forward is effected.

Given that there may be a use case for it, implementing one would not be too hard; but I'm not sure as to the general use case. It could be argued that the conditions related to the possible exceptions, and the required exception guarantees, should be tested for and dealt with outside of the function doing the forwarding.

template <class U, class T>
U wrapper(T&& arg)
{
    return U(forward<T>(arg));
}

template <class U, class T>
U method() 
{
  T t;
  // work with t
  return wrapper<U>(move_if_noexcept(t));
}

Granted, it is "early days" for a lot of this, so that may change.

like image 144
Niall Avatar answered Oct 06 '22 01:10

Niall