Todas as funções mais setter em C ++ 11 devem ser escritas como modelos de função aceitando referências universais?
Considere uma aulaX
comN
variáveis de membro, cada uma de algumascopiável emóvel tipo eN
funções de setter correspondentes. Em C ++ 98, a definição deX
provavelmente seria algo como isto:
class X
{
public:
void set_a(A const& a) { _a = a; }
void set_b(B const& b) { _b = b; }
...
private:
A _a;
B _b;
...
};
Funções de setter de classeX
acima pode ligar ambos para lvalue e rvalue argumentos. Dependendo do argumento atual,poderia resultar na criação de um sistema temporário evai eventualmente resultar em uma atribuição de cópia; devido a isso,não copiável tipos não são suportados por este design.
Com o C ++ 11, temos a semântica de movimento, o encaminhamento perfeito e as referências universais (a terminologia de Scott Meyers), que permitem um uso mais eficiente e generalizado das funções de setter, reescrevendo-as da seguinte maneira:
class X
{
public:
template<typename T>
void set_a(T&& a) { _a = std::forward<T>(a); }
template<typename T>
void set_b(T&& b) { _b = std::forward<T>(b); }
...
private:
A _a;
B _b;
...
};
Referências universais podem se ligar aconst
/não-const
, volatile
/não-volatile
, e para qualquer tipo conversível em geral, evitando a criação de valores temporários e passantes diretamente paraoperator =
. Não copiável, móvel tipos agora são suportados. Possivelmente ligações indesejadas podem ser eliminadas através destatic_assert
ou atravésstd::enable_if
.
Então minha pergunta é: comodiretriz de design, todas as funções de setter (digamos, mais) em C ++ 11 devem ser escritas como modelos de função aceitando referências universais?
Além da sintaxe mais incômoda e da impossibilidade de usar ferramentas auxiliares do tipo Intellisense ao escrever código nessas funções de setter, existem quaisquer desvantagens relevantes com o princípio hipotético "escreve setter funções como modelos de função aceitando referências universais sempre que possível"?