Mover a geração de função de membro
Código:
#include <iostream>
#include <ios>
#include <string>
#include <type_traits>
#include <memory>
struct value
{
~value() = default;
std::unique_ptr<std::string> s;
};
int main()
{
std::cout << std::boolalpha;
std::cout << std::is_move_constructible<value>::value << '\n';
std::cout << std::is_move_assignable<value>::value << '\n';
using str_ptr = std::unique_ptr<std::string>;
std::cout << std::is_move_constructible<str_ptr>::value << '\n';
std::cout << std::is_move_assignable<str_ptr>::value << '\n';
return 0;
}
Saída (compilada com g ++ v4.7.2,http://ideone.com/CkW1tG):
false false true true
Como eu esperava,value
não é mover construtível e não é mover atribuível porque:
~value() = default;
é umdeclarado pelo usuário destrutor, que impede a geração implícita de membros de movimento de acordo com a seção12,8 (ver abaixo). Se o destruidor for removido,value
é mover construtível e mover atribuível, como eu esperavahttp://ideone.com/VcR2eq).
No entanto, quando a definição devalue
é alterado para (http://ideone.com/M8LHEA):
struct value
{
~value() = default;
std::string s; // std::unique_ptr<> removed
};
a saída é:
true true true true
value
é inesperadamente mover construtível e mover atribuível. Estou entendendo mal ou isso é um erro de compilador?
fundo: Eu forneci uma resposta paraisto questão e foi informado de queTree<>
era móvel, mas não tenho certeza e estou tentando determinar com certeza se é ou não.
Seção8.4.2 Funções com default explícito da norma c ++ 11 (projecto n3337):
Funções com default explícito e funções declaradas implicitamente são coletivamente chamadas de funções default, e a implementação deve fornecer definições implícitas para elas (12.1 12.4, 12.8), o que pode significar defini-las como excluídas. Uma função de membro especial é fornecida pelo usuário se for declarada pelo usuário e não for explicitamente padronizada ou excluída em sua primeira declaração. Uma função padrão explicitamente fornecida pelo usuário (ou seja, explicitamente padronizada após sua primeira declaração) é definida no ponto em que é explicitamente padronizada; se tal função é implicitamente definida como excluída, o programa é mal formado. [Nota: Declarar uma função como padrão após sua primeira declaração pode fornecer execução eficiente e definição concisa ao mesmo tempo em que ativa uma interface binária estável para uma base de código em evolução. — End note]
Seção12.8 Copiando e movendo objetos de classe (ponto 9):
If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if - X does not have a user-declared copy constructor, - X does not have a user-declared copy assignment operator, - X does not have a user-declared move assignment operator, - X does not have a user-declared destructor, and - the move constructor would not be implicitly defined as deleted.