Error de compilación de fuerza RVO en el fallo

Hay muchas discusiones aquí sobre cuándo se puede hacer RVO pero no mucho sobre cuándo se hace realmente. Como se indica muchas veces, RVO no se puede garantizar de acuerdo con la Norma, pero¿Hay alguna manera de garantizar que la optimización de RVO tenga éxito o que el código correspondiente no se compile?

Hasta ahora he tenido éxito parcialmente en hacer que los errores de enlace del problema de código cuando RVO falla. Para ello declaro los constructores de copia sin definirlos. Obviamente, esto no es robusto ni factible en los casos excepcionales en los que necesito implementar uno o ambos copiadores, es decir,x(x&&) yx(x const&).

Esto me lleva a mi segunda pregunta:¿Por qué los escritores del compilador han elegido habilitar RVO cuando los constructores de copia definidos por el usuario están en su lugar pero no cuando solo están presentes los constructores de copia predeterminados?

Tercera pregunta:¿Hay alguna otra manera de habilitar RVO para estructuras de datos simples?

Última pregunta (promesa):¿Conoces algún compilador que haga que mi código de prueba se comporte de otra manera que observé con gcc y clang?

Aquí hay un código de ejemplo para gcc 4.6, gcc 4.8 y clang 3.3 que muestra el problema. El comportamiento no depende de la optimización general o la configuración de depuración. Por supuesto opcion--no-elide-constructors hace lo que dice, es decir, apaga RVO.

#include <iostream>
using namespace std;

struct x
{
    x () { cout << "original x address" << this << endl; }
};
x make_x ()
{
    return x();
}

struct y
{
    y () { cout << "original y address" << this << endl; }
    // Any of the next two constructors will enable RVO even if only
    // declared but not defined. Default constructors will not do!
    y(y const & rhs);
    y(y && rhs);
};
y make_y ()
{
    return y();
}

int main ()
{
    auto x1 = make_x();
    cout << "copy of  x address" << &x1 << endl;
    auto y1 = make_y();
    cout << "copy of  y address" << &y1 << endl;
}

Salida:

original x address0x7fff8ef01dff
copy of  x address0x7fff8ef01e2e
original y address0x7fff8ef01e2f
copy of  y address0x7fff8ef01e2f

RVO tampoco parece funcionar con estructuras de datos simples:

#include <iostream>

using namespace std;

struct x
{
    int a;
};

x make_x ()
{
    x tmp;
    cout << "original x address" << &tmp << endl;
    return tmp;
}

int main ()
{
    auto x1 = make_x();
    cout << "copy of  x address" << &x1 << endl;
}

Salida:

original x address0x7fffe7bb2320
copy of  x address0x7fffe7bb2350

ACTUALIZAR: Tenga en cuenta que algunas optimizaciones se confunden muy fácilmente con RVO. Ayudantes de constructores comomake_x son un ejemplo Vereste ejemplo donde la optimización es realmente impuesta por el estándar.

Respuestas a la pregunta(3)

Su respuesta a la pregunta