Vejo uma pergunta semelhante Construtor de movimento padrão recebendo um parâmetro constante , que tem 8 anos, com a resposta Não .
Mas, ao mesmo tempo, um programa ligeiramente modificado com o construtor padrão após a definição da classe:
struct A {
A(const A&&);
};
A::A(const A&&) = default;
aceito pelo EDG 6.7 e lançado recentemente pelo GCC 15.1. Demonstração online: https://gcc.godbolt.org/z/E4qT3sTEq
E um exemplo ainda mais complexo parece funcionar corretamente com estes dois compiladores:
struct A {
int i;
constexpr A(int v) : i(v) {}
constexpr A(const A&&);
};
constexpr int f() {
A a(1);
A b = static_cast<const A&&>( a );
return b.i;
}
constexpr A::A(const A&&) = default;
static_assert( f() == 1 );
Mas o MSVC ainda não gosta disso:
error C2610: 'A::A(const A &&)': is not a special member function or comparison operator which can be defaulted
<source>(13): note: the argument must be a non-const rvalue reference
assim como Clang:
error: the parameter for an explicitly-defaulted move constructor may not be const
Demonstração online: https://gcc.godbolt.org/z/6W9W865vG
Alguma coisa mudou nos últimos 8 anos nessa relação? Qual implementação está correta agora?
A regra em [dcl.fct.def.default] é:
O construtor de movimento declarado implicitamente teria a aparência de
A(A&&)
.A(A const&&)
e difere daquele de uma forma que não corresponde a nenhuma dessas quatro exceções (há um caso especial para definir um construtor de cópia comoC(C&) = default;
, que é o quarto item, mas nada para construtores de movimento).Então caímos na segunda regra. Se este construtor de movimento tivesse sido definido como "deletado" em sua primeira declaração, ele teria sido definido como "deletado". Mas no OP, ele está fora de linha por padrão — então isso deveria estar incorreto.
Em C++17 (assim como em C++14 ), isso ainda estaria malformado (mesmo que a função tivesse sido definida por padrão em sua primeira declaração). Portanto, embora as regras sobre a definição de padrões tenham sido um pouco flexibilizadas, essas flexibilizações não afetariam este exemplo.