C++ identity function I've implemented an identity function (well, actually a functor struct) in C++. The goal is that every occurrence of an expression expr in the code can be substituted by identity(expr) without changing the semantics of the program at all.

I make it a struct with a templated operator() instead of simply a function template because this enables us to pass identity as an argument to other functions (say std::transform) without needing to specify the type (e.g., identity&lt;std::pair&lt;std::vector&lt;int&gt;::const_iterator, std::vector&lt;double&gt;::const_iterator&gt;&gt;).

The code is written in C++14.

#include &lt;utility&gt;

static constexpr struct identity_t {
    template&lt;typename T&gt;
    constexpr decltype(auto) operator()(T&amp;&amp; t) const noexcept
    {
        return std::forward&lt;T&gt;(t);
    }
} identity{};


Usage:

int x = 42;
identity(x) = 24;

constexpr int size = 123;
int arr[identity(size)] = {};

vector&lt;int&gt; v1 = {1, 2, 3, 4}, v2;
v2.reserve(v1.size());
transform(v1.cbegin(), v1.cend(),
          back_inserter(v2),
          identity);

template&lt;typename T&gt;
class my_container {
public:
    template&lt;typename F&gt;
    auto flat_map(F&amp;&amp; f) const { ... }

    auto flatten() const { return flat_map(identity); }

    ...
};


Since identity(expr) is nothing more than a cast, performance should not be a problem. I'm concerned whether there are cases in which this implementation fails to keep the program's behavior unchanged. If there are, how can I fix the implementation?

EDIT: I changed "a variable x" in the first paragraph to "an expression expr". The latter is more accurate.
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.