S in the expression typename std::remove_reference<S>::type represents an inaccessible context (especially because S appears in the nested specifier of the type specified using an identifier with qualification). Non-derivable contexts, as the name implies, are contexts in which the template argument cannot be inferred.
This case provides a simple example to understand why. Say I had:
int i; forward(i);
What would be S ? It can be int , int& or int&& - all these types will lead to the correct argument type for the function. It is simply not possible for the compiler to determine which S you really mean here, so it is not trying. It is not output, so you must explicitly indicate which S you mean:
forward<int&>(i);
Barry source share