operador de seta (->) no cabeçalho da função

128

Me deparei com o seguinte código:

template <typename T, typename T1> auto compose(T a, T1 b) -> decltype(a + b) {
   return a+b;
}

Há uma coisa que não consigo entender:

Onde eu poderia descobrir o que o operador de seta ( ->) significa no cabeçalho da função? Eu acho que, logicamente, o ->operador determina um tipo que autoserá deduzido, mas eu quero esclarecer isso. Não consigo encontrar nenhuma informação.

user1234567
fonte
2
Faz parte da sintaxe do tipo de retorno à direita. Veja stackoverflow.com/a/4113390/962089
chris
2
Não é um operador, mas uma parte da sintaxe.
texasbruce
1
Em resposta a "onde posso ler?", A especificação C ++ é mais autorizada. Na falta de fundos ou no desejo de gastar $$, o último esboço de trabalho geralmente é próximo o suficiente e sem custo. Essas especificações são altamente tecnológicas, portanto, sem familiaridade com a leitura das especificações ISO, tente cplusplus.com ou cppreference.com ou outros sites que não sejam oficiais, mas geralmente são muito precisos. Nota: o tipo de retorno à direita pode ser omitido, começando com C ++ 14.
Les

Respostas:

205

No C ++ 11, existem duas sintaxes para declaração de função:

     identificador de tipo retorno ( declarações-argumento ... )

e

    auto identificador ( argumento-declarações ... ) -> return_type

Eles são equivalentes. Agora, quando são equivalentes, por que você deseja usar o último? Bem, o C ++ 11 introduziu essa decltypecoisa interessante que permite descrever o tipo de uma expressão. Portanto, você pode derivar o tipo de retorno dos tipos de argumento. Então você tenta:

template <typename T1, typename T2>
decltype(a + b) compose(T1 a, T2 b);

e o compilador lhe dirá que ele não sabe o que ae bestá no decltypeargumento. Isso ocorre porque eles são declarados apenas pela lista de argumentos.

Você poderia solucionar o problema facilmente usando declvalos parâmetros de modelo que já foram declarados. Gostar:

template <typename T1, typename T2>
decltype(std::declval<T1>() + std::declval<T2>())
compose(T1 a, T2 b);

exceto que está ficando muito detalhado agora. Portanto, a sintaxe da declaração alternativa foi proposta e implementada e agora você pode escrever

template <typename T1, typename T2>
auto compose(T1 a, T2 b) -> decltype(a + b);

e é menos detalhado e as regras de escopo não precisam ser alteradas.


Atualização do C ++ 14: o C ++ 14 também permite apenas

    auto identificador ( argumento-declarações ... )

desde que a função esteja totalmente definida antes do uso e todas as returninstruções sejam deduzidas para o mesmo tipo. A ->sintaxe permanece útil para funções públicas (declaradas no cabeçalho) se você deseja ocultar o corpo no arquivo de origem. Obviamente, isso não pode ser feito com modelos, mas existem alguns tipos concretos (geralmente derivados da metaprogramação de modelos) que são difíceis de escrever de outra forma.

Jan Hudec
fonte
2
resposta muito boa, clara e informativa @Jan Hudec. Polegares para cima. Existe algo alterado C++14conforme eu uso autopara returndigitar essa função sem a necessidade da -> decltype(a + b)peça. É redundante agora ou tem outros casos em que ainda deve ser usado? ou é uma extensão específica do compilador?
Shadi
1
@Shadi, C ++ 14 inclui N3638 , que permite dedução do tipo de retorno declarado como auto, sem a ->notação, desde que a função esteja totalmente definida antes do uso e todas as returninstruções sejam deduzidas para o mesmo tipo. A ->notação ainda será útil se você desejar usar a dedução para função pública enquanto oculta o corpo no arquivo de origem.
Jan Hudec
23

Em inglês simples, ele diz que o tipo de retorno é o tipo inferido da soma de ae b.

Murrekatt
fonte