copy elision: move constructor não chamado ao usar a expressão ternária na instrução de retorno?

Considere o seguinte exemplo:

#include <cstdio>

class object
{
public:
    object()
    {
        printf("constructor\n");
    }

    object(const object &)
    {
        printf("copy constructor\n");
    }

    object(object &&)
    {
        printf("move constructor\n");
    }
};

static object create_object()
{
    object a;
    object b;

    volatile int i = 1;

// With #if 0, object's copy constructor is called; otherwise, its move constructor.
#if 0
    if (i)
        return b; // moves because of the copy elision rules
    else
        return a; // moves because of the copy elision rules
#else
    // Seems equivalent to the above, but behaves differently.
    return i ? b : a; // copies (with g++ 4.7)
#endif
}

int main()
{
    auto data(create_object());

    return 0;
}

E considere este bit a partir do C ++ 11 Working Draft, n3337.pdf, 12.8 [class.copy], ponto 32:

Quando os critérios para a elisão de uma operação de cópia forem atendidos ou forem atendidos, exceto pelo fato de que o objeto de origem é um parâmetro de função,e o objeto a ser copiado é designado por um lvalue, a resolução de sobrecarga para selecionar o construtor para a cópia é executada primeiro como se o objeto fosse designado por um rvalue. Se a resolução de sobrecarga falhar ou se o tipo do primeiro parâmetro do construtor selecionado não for uma referência de valor para o tipo do objeto (possivelmente qualificada para cv), a resolução de sobrecarga será executada novamente, considerando o objeto como um lvalue. [Nota: Esta resolução de sobrecarga de dois estágios deve ser executada independentemente de a elisão da cópia ocorrer. Ele determina o construtor a ser chamado se a elisão não for executada e o construtor selecionado deve estar acessível mesmo se a chamada for elidida. - end note]

Assim, se usarmos#if 1 No exemplo, o construtor de movimento é tentado pela primeira vez ao retornar o objeto e, em seguida, o construtor de cópia. Como temos um construtor de movimento, ele é usado no lugar do construtor de cópia.

No ultimoreturn declaração emcreate_object() No entanto, observamos que o construtor de movimentação não é usado. Isso é ou não é uma violação das regras da linguagem? A linguagem requer que o construtor de movimento seja usado no últimoreturn declaração?

questionAnswers(1)

yourAnswerToTheQuestion