C ++ 0x mostra um exemplo de uso std::forward
:
template<class T>
void foo(T&& arg)
{
bar(std::forward<T>(arg));
}
Quando é vantajoso usar std::forward
sempre?
Além disso, ele requer o uso &&
na declaração de parâmetros, é válido em todos os casos? Eu pensei que você tinha que passar temporários para uma função se a função foi declarada com &&
ela, então pode ser chamado com qualquer parâmetro?
Por fim, se eu tiver uma chamada de função como esta:
template<int val, typename... Params>
void doSomething(Params... args) {
doSomethingElse<val, Params...>(args...);
}
Devo usar isso em seu lugar:
template<int val, typename... Params>
void doSomething(Params&&... args) {
doSomethingElse<val, Params...>(std::forward<Params>(args)...);
}
Além disso, se usar os parâmetros duas vezes na função, ou seja, encaminhar para duas funções ao mesmo tempo, é aconselhável usar std::forward
? Não std::forward
converterá a mesma coisa em temporária duas vezes, movendo a memória e a invalidará para um segundo uso? O código a seguir está ok:
template<int val, typename... Params>
void doSomething(Params&&... args) {
doSomethingElse<val, Params...>(std::forward<Params>(args)...);
doSomethingWeird<val, Params...>(std::forward<Params>(args)...);
}
Estou um pouco confuso std::forward
, e eu ficaria feliz em esclarecer.
fonte
Args...&& args
?A resposta de Kerrek é muito útil, mas não responde completamente à pergunta do título:
Para responder, devemos primeiro introduzir uma noção de referências universais . Scott Meyers deu esse nome e hoje em dia é chamado de referência de encaminhamento. Basicamente, quando você vê algo assim:
tenha em mente que
param
não é uma referência de valor (como alguém pode ser tentado a concluir), mas uma referência universal *. As referências universais são caracterizadas por uma forma muito restrita (apenasT&&
, sem qualificadores const ou similares) e por dedução de tipo - o tipoT
será deduzido quandof
for invocado. Em poucas palavras, as referências universais correspondem às referências rvalue se forem inicializadas com rvalues, e às referências lvalue se forem inicializadas com lvalues.Agora é relativamente fácil responder à pergunta original - aplique
std::forward
a:Um exemplo para o primeiro caso:
No código acima, não queremos
prop
ter um valor desconhecido após aother.set(..)
conclusão, portanto, nenhum encaminhamento acontece aqui. No entanto, ao ligarbar
, encaminhamosprop
como já terminamos ebar
podemos fazer o que quiser com ele (por exemplo, movê-lo).Um exemplo para o segundo caso:
Este modelo de função deve passar
prop
para o valor de retorno se for um rvalue e copiá-lo se for um lvalue. No caso de omitirmosstd::forward
no final, sempre criaríamos uma cópia, que é mais cara quandoprop
ocorre um rvalor.* para ser totalmente preciso, uma referência universal é um conceito de obter uma referência rvalue para um parâmetro de modelo não qualificado por cv.
fonte
Este exemplo ajuda? Lutei para encontrar um exemplo útil e não genérico de std :: forward, mas encontrei um exemplo de conta bancária que repassamos ao longo do dinheiro para ser depositado como argumento.
Portanto, se tivermos uma versão const de uma conta, esperamos que, quando passamos para o nosso modelo de depósito <>, que a função const seja chamada; e isso gera uma exceção (a ideia era que era uma conta bloqueada!)
Se tivermos uma conta não const, poderemos modificar a conta.
Construir:
Saída esperada:
fonte