2012-05-10 12 views
82

Poiché i modelli sono definiti all'interno di intestazioni e il compilatore è in grado di determinare se l'inlining di una funzione è vantaggioso, ha senso? Ho sentito che i compilatori moderni sanno meglio quando integrare una funzione e ignorano il suggerimento inline.Ha senso usare la parola chiave inline con i modelli?


modifica: Vorrei accettare entrambe le risposte, ma questo non è possibile. Per chiudere il problema accetto la risposta phresnel, perché ha ricevuto più voti e ha formalmente ragione, ma come ho detto nei commenti considero le risposte Puppy e Componente 10 come anche quelle corrette , da un diverso punto di vista.

Il problema è nella semantica C++, che non è rigorosa in caso di parola chiave inline e di inlining. phresnel dice "scrivi in ​​linea se lo intendi", ma ciò che in realtà è inteso da inline non è chiaro in quanto si è evoluto dal suo significato originale a una direttiva che "ferma i compilatori lamentarsi di violazioni ODR" come dice Puppy.

risposta

65

Non è irrilevante. E no, non tutti i modelli di funzioni sono inline per impostazione predefinita. Lo standard è ancora più esplicito a questo proposito in specializzazione esplicita ([temp.expl.spec])

disporre di:

a.cc

#include "tpl.h" 

b.cc

#include "tpl.h" 

tpl.h (tratto da specializzazione esplicita):

#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 

compilare questo, et voilà:

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 

Non affermando inline quando si fa esplicita di istanza può anche portare a problemi.

Quindi, in sintesi: Per i modelli di funzione non pienamente specializzate, vale a dire quelli che portano almeno un tipo sconosciuto, è possibile omettere inline, e non ricevono errori, ma ancora non sono inline. Per le specializzazioni complete, ad esempio quelle che utilizzano solo tipi noti, non puoi ometterlo.

Proporre la regola empirica: Scrivere inline se si intende e deve essere coerente. Ti fa pensare meno a se o non solo perché puoi. (Questa regola empirica è conforme a Vandevoorde's/Josuttis's C++ Template: The Complete Guide).

+0

È vero per le specializzazioni esplicite: sono come semplici funzioni. Ma qui -> 'template inline T g (T) {}' inline non è richiesto e potresti aver scritto 'template T g (T) {}' – doc

+1

Uno potrebbe averlo scritto, vero. Ma ciò non implica la rigidità, anche se sembra così. Anche Vandevoorde e Josuttis affermano esattamente ciò in _C++ Templates: La guida completa_ –

+0

C'è una dichiarazione un po 'più debole che i modelli possono avere più definizioni (3.2/5) -> http://stackoverflow.com/a/10211420/205955 Sono d'accordo che questo non implica che siano formalmente in linea. Tuttavia, tutto si riduce a questo in pratica. Quindi, entrambe le risposte sono corrette da diversi punti di vista. – doc

21

È irrilevante. Tutti i modelli sono già inline - per non parlare del fatto che a partire dal 2012 l'unico uso della parola chiave inline consiste nel bloccare i compilatori che insultano le violazioni ODR. Sei assolutamente corretto: il tuo compilatore di generazione corrente saprà cosa inline da solo e probabilmente lo farà anche tra le unità di traduzione.

+5

Lo standard non indica che tutti i modelli sono in linea. –

+10

@phresnel: Ma i template hanno la stessa semantica delle funzioni marcate in linea (cioè, possono essere passate al linker definizioni multiple equivalenti, che ne selezionano una). Questo, non in linea, è la vera funzione della parola chiave 'inline'. –

+0

@BenVoigt: conosco il significato ODR di 'inline'. Forse dare un'occhiata alla mia risposta qui sotto (o sopra, a seconda dell'ordinamento scelto). Per i modelli non specializzati, ovviamente hai ragione, ma non è formalmente lo stesso. –

1

Come suggerito, inline è un suggerimento per il compilatore e nulla più. Può scegliere di ignorarlo o, in effetti, per le funzioni inline non contrassegnate in linea.

Utilizzo di inline con i modelli utilizzati per essere un (scarso) modo di aggirare il problema che ogni unità di compilazione creerebbe un oggetto separato per la stessa classe di modelli che causerebbe quindi problemi di duplicazione al momento del collegamento. Usando inline (credo) il nome mangling funziona in modo diverso, che aggira lo scontro del nome al momento del collegamento, ma a spese di un codice enormemente gonfio.  

Marshall Cline explains it here meglio di me.

+0

@Xeo: Non era così. Controlla qui: http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Template-Instantiation.html#Template-Instantiation Suppongo che sia cambiato più di recente, ecco perché stavo parlando al passato. –

+1

@Xeo: puoi indicarmi la parte di The Standard che afferma che i modelli di funzione sono sempre in linea? Perché, loro non lo sono. –

+0

@phresnel: Interessante, potrei giurare di averlo letto nello standard. Forse l'ho mescolato con il fatto che i modelli di funzione sono esenti dall'ODR ('§14.5.5.1 p7 & p8'). Il mio male, ho rimosso il commento sbagliato. – Xeo

Problemi correlati