C++ identity function
Well, that looks like a straightforward use of perfect forwarding in the parameter (T&amp;&amp;, std::forward&lt;T&gt;) and in the return type (decltype(auto)). So yep, you've got it.

There are plenty of places in C++ where x and identity(x) don't do the same thing, either because x is a name as well as an expression, or because x is a construct that looks like an expression but technically is not one. (Personally, I consider almost all of these places to be mistakes in the design of C++.) Here are the ones I can think of.

Replacing identity(x) with x in all of the following examples changes the behavior of the code sample.



As mentioned in the comments on the question, the name of a function template can deduce what kind of function pointer to decay to:

template&lt;class T&gt; void f(T) {}
void (*fp)(int) = identity(f);




The name of a local variable gets copy elision (a.k.a. Named Return Value Optimization, or NRVO):

struct S {
    S() {}
    S(const S&amp;) { puts("copy"); }
    S(S&amp;&amp;) { puts("move"); }
};
S f() {
    S s;
    return identity(s);
}
int main() { f(); }




The name of a local variable is treated as an rvalue in the context of return:

struct S {
    S() {}
    S(const S&amp;) { puts("copy"); }
    S(S&amp;&amp;) { puts("move"); }
};
std::any f() {
    S s;
    return identity(s);
}
int main() { f(); }




Lifetime extension applies to temporaries whose construction is "visible" in some sense that is extremely subtle when I start thinking hard about it. Interposing the call to identity disables lifetime extension.

struct S {
    S() { puts("ctor"); }
    S(const S&amp;) = delete;
    S(S&amp;&amp;) = delete;
    ~S() { puts("dtor"); }
};
int main() {
    const S&amp; x = identity(S());
    puts("done");
}




Braced initializers and string literals look like expressions, but in the context of an initializer, they're special cases:

const char x[] = identity("hello");
int y = identity({5});




Now, I can't imagine how you'd use identity in your codebase where any of these quirks might matter; but then, I don't quite see how you plan to use identity at all. Your only fleshed-out example is just using std::transform(..., identity) as a verbose way of writing std::copy(...), which doesn't seem very useful.