even if NonCopyNonMoveType has neither an accessible copy constructor nor an accessible move constructor.
Given that definition of f, also the following is valid
NonCopyNonMoveType g() {
return f();
}
However, the expression function_ref<NonCopyNonMoveType()>(f) will not compile.
The usual constructor is disabled because the requirement std::is_convertible_v<std::invoke_result_t<decltype(f)>,NonCopyNonMoveType> is not met.
That is the case because convertibility tests the possibility to construct a newfunction_ref return value from an rvalue of an existing return value of the supplied callable (in this case, it would be a move). However, under the new move ellision rules, no such move will actually happen. Therefore, in this case, the requirement rejects a callable that would be perfectly valid.
In C++17 and later the new mandatory ellision of copy/move operations allow the following function:
even if
NonCopyNonMoveType
has neither an accessible copy constructor nor an accessible move constructor.Given that definition of
f
, also the following is validHowever, the expression
function_ref<NonCopyNonMoveType()>(f)
will not compile.The usual constructor is disabled because the requirement
std::is_convertible_v<std::invoke_result_t<decltype(f)>,NonCopyNonMoveType>
is not met. That is the case because convertibility tests the possibility to construct a newfunction_ref
return value from an rvalue of an existing return value of the supplied callable (in this case, it would be a move). However, under the new move ellision rules, no such move will actually happen. Therefore, in this case, the requirement rejects a callable that would be perfectly valid.