Faz algum sentido usar palavras-chave em linha com modelos?

119

Como os modelos são definidos nos cabeçalhos e o compilador é capaz de determinar se uma função embutida é vantajosa, isso faz algum sentido? Ouvi dizer que os compiladores modernos sabem melhor quando alinhar uma função e estão ignorando a inlinedica.


editar: eu gostaria de aceitar as duas respostas, mas isso não é possível. Para encerrar a questão, estou aceitando a resposta do phresnel , porque ele recebeu a maioria dos votos e ele está formalmente certo, mas, como mencionei nos comentários, considero as respostas do Puppy e do Componente 10 também corretas, de um ponto de vista diferente. .

O problema está na semântica do C ++, que não é rigorosa no caso de inlinepalavras-chave e inlining. phresnel diz "escreva em linha, se você quiser", mas o que realmente significa inlinenão é claro, pois evoluiu de seu significado original para uma diretiva que "impede os compiladores de reclamar sobre violações de ODR" como diz Puppy .

doc
fonte

Respostas:

95

Não é irrelevante. E não, nem todos os modelos de função são inlinepor padrão. O padrão é até explícito sobre ele na especialização explícita ([temp.expl.spec])

Tenha o seguinte:

a.cc

#include "tpl.h"

b.cc

#include "tpl.h"

tpl.h (extraído da Explicit Specialization):

#ifndef TPL_H
#define TPL_H
template<class T> void f(T) {}
template<class T> inline T g(T) {}

template<> inline void f<>(int) {} // OK: inline
template<> int g<>(int) {} // error: not inline
#endif

Compile isso e pronto:

g++ a.cc b.cc
/tmp/ccfWLeDX.o: In function `int g<int>(int)':
inlinexx2.cc:(.text+0x0): multiple definition of `int g<int>(int)'
/tmp/ccUa4K20.o:inlinexx.cc:(.text+0x0): first defined here
collect2: ld returned 1 exit status

Não declarar inlineao fazer instanciação explícita também pode levar a problemas.

Então, em resumo : para modelos de funções não totalmente especializados, ou seja, modelos que possuem pelo menos um tipo desconhecido, você pode omitir inlinee não receber erros, mas ainda não o são inline. Para especializações completas, ou seja, que usam apenas tipos conhecidos, você não pode omitir.

Regra geral proposta : escreva inlinese quiser e seja consistente. Isso faz você pensar menos se deve ou não apenas porque pode. (Esta regra geral está em conformidade com o modelo C ++ de Vandevoorde / Josuttis : o guia completo ).

Sebastian Mach
fonte
2
Alguém poderia ter escrito, é verdade. Mas isso não implica em ingenuidade, mesmo que pareça assim. Vandevoorde e Josuttis também afirmam exatamente isso em modelos C ++: O guia completo
Sebastian Mach
43
A especialização explícita não é um modelo.
Filhote
2
@DeadMG: Ainda assim, uma função normal é preferida a uma especialização completa na pesquisa; portanto, se elas não são modelo, nem não modelo, o que são então?
Sebastian Mach
13
Esta resposta está incorreta. Uma especialização explícita de um modelo é uma função, não um modelo. Essa função não se torna inlineapenas porque o modelo que foi especializado está marcado com inline. Portanto, inlineo modelo é completamente irrelevante. Se essa função deve inlineou não ter nada a ver com o fato de ser gerada por meio de uma especialização de modelo (e há respostas melhores do que as que abordam quando usar inline). A resposta do @Puppy abaixo está correta, esta não está. A adição inlinede um modelo é irrelevante e clang-tidy, na verdade , será removida.
precisa saber é o seguinte
6
Além disso, o exemplo apenas mostra problemas de ODR para funções normais (o comportamento não tem nada a ver com modelos). Para tentar mostrar que isso inlinenão é irrelevante, o exemplo deve cobrir o caso de se especializar explicitamente template<> void f<>(int) {} sem a inlinepalavra - chave. Porém, mesmo assim, alterar o inlineespecificador no modelo não faz diferença, porque a marcação inlineou não do modelo é irrelevante.
precisa saber é o seguinte
34

É irrelevante. Todos os modelos já são inline- sem mencionar que, a partir de 2012, o único uso da inlinepalavra-chave é parar os compiladores queixam-se de violações do ODR. Você está absolutamente correto - seu compilador da geração atual saberá o que incluir sozinho e provavelmente poderá fazê-lo mesmo entre unidades de tradução.

Cachorro
fonte
11
O padrão não indica que todos os modelos estão em linha.
Sebastian Mach
16
@phresnel: Mas os modelos têm a mesma semântica que as inlinefunções marcadas (ou seja, várias definições equivalentes podem ser passadas para o vinculador, que selecionará uma). Essa não é a função real da inlinepalavra - chave.
Ben Voigt
2
@BenVoigt: Eu sei sobre o significado de ODR inline. Talvez dê uma olhada na minha resposta abaixo (ou acima, dependendo da classificação escolhida). Para modelos não especializados, é claro que você está certo, mas formalmente não é o mesmo.
Sebastian Mach
3
@DeadMG: Não há requisito em C ++ que um modelo de função seja implementado em um arquivo de cabeçalho; pode ser implementado em qualquer lugar. Para refletir isso, costumo recomendar a marcação do inlineque deveria estar embutido. Geralmente não faz diferença, mas, em padrão, eles não são os mesmos e nem todos estão alinhados. Aceito sua posição dizendo: "É irrelevante", mas, por padrão, nem todos os modelos estão em linha, apenas para você como um usuário C ++ - eles aparecem como se.
Sebastian Mach
7
Seu comentário sobre a resposta aceita de que a especialização explícita não é um modelo (o que é óbvio depois de ser dito, é claro ...) é talvez a coisa mais útil nesta página. Você se importaria de adicioná-lo à sua resposta também?
Kyle Strand
6

Como você sugeriu, inlineé uma dica para o compilador e nada mais. Ele pode optar por ignorá-lo ou, de fato, incorporar funções não marcadas como incorporadas.

O uso de inlinemodelos costumava ser uma maneira (ruim) de contornar o problema de que cada unidade de compilação criaria um objeto separado para a mesma classe de modelo, o que causaria problemas de duplicação no tempo do link. Ao usar inline(eu acho), o nome mangling funciona de maneira diferente, contornando o conflito de nomes no tempo do link, mas à custa de um código muito inchado.  

Marshall Cline explica aqui melhor do que eu.

Componente 10
fonte
@ Xeo: Isso não costumava ser o caso. Verifique aqui: gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/… Suponho que isso mudou mais recentemente, é por isso que eu estava falando no passado.
Component 10
2
@ Xeo: Você pode me indicar a parte do padrão que afirma que os modelos de função estão sempre alinhados? Porque eles não são.
Sebastian Mach
@phresnel: Interessante, eu poderia jurar que li isso na norma. Talvez eu tenha misturado isso com o fato de que os modelos de função estão isentos do ODR ( §14.5.5.1 p7 & p8). Meu mal, eu removi o comentário errado.
Xeo
@Component 10 Por que você acha que é má maneira de conseguir questão rodada compilação
Kapil