Q:

Move elision optimization

Consider two implementations of a class:
struct S1
{
    std::vector< T > v;
    void push(T && x) { v.push_back(std::move(x)); }
    void push(T const & x) { push(T(x)); }
    void pop() { v.pop_back(); }
    void replace(T && x) { pop(); push(std::move(x)); }
    void replace(T const & x) { replace(T(x)); }
};

struct S2
{
    std::vector< T > v;
    void push(T x) { v.push_back(std::move(x)); }
    void pop() { v.pop_back(); }
    void replace(T x) { pop(); push(std::move(x)); }
};

S1's push overloads express exactly what I want. S2's push is a way to express it in a less verbose way.
But I worry that there is a drawback connected with the excessive move-construction of objects. 
Can modern compilers reduce the expression std::move(T(std::move(t))) to std::move(t) for some t where decltype(t) is T&? Can modern compilers optimize out unnecessary moves? Or is this prohibited by the standard?

A:

No, that elision is not legal, other than under as-if optimization.
Now, if foo() is an expression that returns a T, then S{}.push(foo()) can elide the move from the return value of foo() into the argument of push: only one move is done.
But if we S{}.push(std::move(foo()), the explicit std::move blocks the possibility of elision.
An approach that is often better is emplace based operations instead of push based operations.
template<class...Args>
void emplace(Args&&...args) {
  v.emplace_back( std::forward<Args>(args)... );
}

this lets you pass the parameters to construct the T to the object, and cause it to be directly constructed in the sink (the vector) rather than moved or copied into it.
Optionally:
template<class...Args,
  decltype(T(std::declval<Args&&>()...))* =0
>
void emplace(Args&&...args) {
  v.emplace_back( std::forward<Args>(args)... );
}

if you want SFINAE support.  A comment saying "we expect a T to be constructed here", if not obvious, is also polite.

