2012-05-10 14 views
82

Ponieważ szablony są zdefiniowane w nagłówkach, a kompilator jest w stanie określić, czy wstawianie funkcji jest korzystne, czy ma to jakiś sens? Słyszałem, że nowoczesne kompilatory wiedzą lepiej, kiedy wstawić funkcję i ignorują podpowiedź inline.Czy ma sens stosowanie inline keyword z szablonami?


edytuj: Chciałbym przyjąć obie odpowiedzi, ale nie jest to możliwe. Aby zamknąć ten problem, przyjmuję odpowiedź: phresnel, ponieważ otrzymała ona najwięcej głosów i ma formalne prawo, ale jak wspomniałem w komentarzach, uważam odpowiedzi i oraz jako odpowiedźrównież jako prawidłowe. z innego punktu widzenia.

Problem dotyczy semantyki C++, która nie jest ścisła w przypadku słowa kluczowego i inliningowego w przypadku słowa kluczowego inline. phresnel mówi "napisz w linii, jeśli masz na myśli to", ale to, co w rzeczywistości oznacza inline, nie jest jasne, ponieważ ewoluowało od pierwotnego znaczenia do dyrektywy, która "zatrzymuje kompilatory gadające o naruszeniach ODR", jak mówi Puppy.

Odpowiedz

65

Nie jest to bez znaczenia. I nie, nie każdy szablon funkcji jest domyślnie ustawiony na inline. Średnia jest nawet wprost o niej w Explicit specjalizacji ([temp.expl.spec])

mają następujące:

a.cc

#include "tpl.h" 

b.cc

#include "tpl.h" 

tpl.h (zaczerpnięte z Explicit specjalizacji):

#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 

skompilować ten, et voila:

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 

Nie stwierdzając inline robiąc wyraźną instancji może również prowadzić do problemów.

Tak w skrócie: Dla nie w pełni wyspecjalizowanych szablonów funkcyjnych, to znaczy te, które posiadają co najmniej jeden nieznanego typu, można pominąć inline i nie pojawiają się błędy, ale wciąż nie są inline. W przypadku pełnych specjalizacji, tj. Takich, które używają tylko znanych typów, nie można tego pominąć.

Proponowana zasada: Napisz inline, jeśli masz na myśli to i po prostu bądź konsekwentny. To sprawia, że ​​myślisz mniej o tym, czy nie tylko dlatego, że możesz. (Ta zasada jest zgodna z Vandevoorde's/Josuttis's C++ Template: The Complete Guide).

+0

Dotyczy to jawnych specjalizacji - są one jak zwykłe funkcje. Ale tutaj -> 'szablon wbudowany T g (T) {}' wbudowany nie jest wymagany i mógłbyś napisać 'szablon T g (T) {}' – doc

+1

Można by napisać, prawda. Ale to nie implikuje inności, nawet jeśli wygląda tak. Vandevoorde i Josuttis również stwierdzają dokładnie, że w szablonach _C++: Kompletny Guide_ –

+0

Jest nieco słabsze stwierdzenie, że szablony mogą mieć wiele definicji (3.2/5) -> http://stackoverflow.com/a/10211420/205955 Zgadzam się, że nie oznacza to, że są one formalnie wbudowane. Jednak wszystko sprowadza się do tego w praktyce. Tak więc obie odpowiedzi są poprawne z różnych punktów widzenia. – doc

21

To nieistotne. Wszystkie szablony są już oznaczone jako inline - nie wspominając o tym, że począwszy od 2012 roku jedynym użytym słowem kluczowym inline jest zatrzymanie kompilatorów dłubiących w sprawie naruszeń ODR. Jesteś absolutnie poprawny - twój kompilator obecnej generacji będzie wiedział, co należy wstawić na własną rękę i może to zrobić nawet między jednostkami tłumaczeniowymi.

+5

Standard nie stwierdza, że ​​wszystkie szablony są wbudowane. –

+10

@phresnel: Ale szablony mają tę samą semantykę co funkcje "inline" (to znaczy, że wiele równoważnych definicji może być przekazanych do linkera, który wybierze jeden). To, nie wpisując, jest prawdziwą funkcją słowa kluczowego 'inline'. –

+0

@BenVoigt: Wiem o znaczeniu ODR słowa 'inline'. Może zajrzyj do mojej odpowiedzi poniżej (lub powyżej, w zależności od wybranego sortowania). W przypadku nie specjalistycznych szablonów masz oczywiście rację, ale formalnie nie jest to to samo. –

1

Zgodnie z sugestią, inline jest wskazówką dla kompilatora i nic więcej. Może go zignorować lub, w rzeczy samej, wbudować funkcje, które nie są zaznaczone w linii.

Używanie szablonów było (ubogim) sposobem na zajęcie się kwestią, że każda jednostka kompilacyjna utworzyłaby oddzielny obiekt dla tej samej klasy szablonowej, co spowodowałoby problemy z duplikacją w czasie połączenia. Dzięki użyciu inline (jak sądzę) wymieszanie nazwy działa inaczej, co koliduje ze zderzeniem nazwy w czasie linku, ale kosztem bardzo rozdętego kodu.  

Marshall Cline explains it here lepiej niż ja.

+0

@Xeo: Tak się nie działo. Sprawdź tutaj: http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Template-Instantiation.html#Template-Instantiation Przypuszczam, że ostatnio się zmieniło, dlatego rozmawiałem w czasie przeszłym. –

+1

@Xeo: Czy możesz wskazać mi część Standardu, która stwierdza, że ​​szablony funkcji są zawsze wstawiane? Ponieważ nie są. –

+0

@phresnel: Interesujące, mógłbym przysiąc, że przeczytałem to w standardzie. Może pomieszałem to z faktem, że szablony funkcji są wyłączone z ODR ("§14.5.5.1 p7 i p8"). Mój zły, usunąłem zły komentarz. – Xeo