Чи має сенс використовувати вбудоване ключове слово з шаблонами?


119

Оскільки шаблони визначені в заголовках, і компілятор може визначити, чи вкладення функції вигідніше, чи має це сенс? Я чув, що сучасні компілятори краще знають, коли вбудувати функцію, і ігнорують inlineпідказку.


редагувати: Я хотів би прийняти обидві відповіді, але це неможливо. Щоб закрити питання, я приймаю відповідь Френеля , тому що він отримав більшість голосів, і він формально правий, але, як я вже згадував у коментарях, я вважаю відповіді Щеня та Компонента 10 як правильні, з іншої точки зору. .

Проблема полягає в семантиці С ++, що не є суворим у випадку inlineключових слів та інліній. phresnel каже: "пишіть інлайн, якщо ви це маєте на увазі", але те, що насправді мається на увазі, inlineне зрозуміло, оскільки воно перейшло від його початкового значення до директиви, що "зупиняє компіляторів, що кусаються про порушення ODR", як говорить Щеня .

Відповіді:


96

Це не має значення. І ні, не кожен шаблон функції inlineза замовчуванням. Стандарт навіть про нього явно виражений у явній спеціалізації ([temp.expl.spec])

Майте наступне:

a.cc

#include "tpl.h"

b.cc

#include "tpl.h"

tpl.h (взято з явної спеціалізації):

#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

Скомпілюйте це та ін. 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

Якщо не inlineвказати, коли робити явну інстанцію, також може виникнути проблема.

Отже, підсумовуючи : Для не повністю спеціалізованих шаблонів функцій, тобто для тих, що мають принаймні один невідомий тип, ви можете опускати inlineта не отримувати помилок, але все ж вони не є inline. Для повної спеціалізації, тобто тих, що використовують лише відомі типи, ви не можете її опустити.

Пропоноване правило : напишіть, inlineякщо ви це маєте на увазі, і просто будьте послідовними. Це змушує вас менше думати про те, чи потрібно, чи не тому, що можете. (Це правило виконується відповідно до шаблону C ++ Вандевуарда / Йосуттіса : Повне керівництво ).


2
Можна було б написати, правда. Але це не означає точності, навіть якщо це виглядає так. Вандевурд і Йосуттіс також стверджують, що це в шаблонах C ++: Повний путівник
Себастьян Мах

43
Явна спеціалізація не є шаблоном.
Щеня

2
@DeadMG: І все-таки нормальна функція віддається перевазі повній спеціалізації при пошуку, тож якщо вони не шаблонні, ані не шаблонні, що це тоді?
Себастьян Мах

13
Ця відповідь невірна. Явна спеціалізація шаблону - це функція, а не шаблон. Ця функція не стає inlineлише тому, що шаблон, який був спеціалізованим, позначений inline. Так що inlineна шаблон абсолютно не має значення. Будь-яка функція повинна бути inlineчи ні, не має нічого спільного з її генеруванням за допомогою спеціалізації шаблону (і є кращі відповіді, ніж ця адреса, коли використовувати inline). @Puppy відповідь нижче правильна, ця - ні. Додавання inlineдо шаблону не має значення і clang-tidyфактично його видалить.
gnzlbg

6
Крім того, приклад просто демонструє проблеми ODR для нормальних функцій (поведінка там не має нічого спільного з шаблонами). Для того, щоб спробувати показати , що inlineне мати ніякого значення, приклад повинен охоплювати випадок явно спеціалізується template<> void f<>(int) {} без на inlineключове слово. Але навіть тоді зміна inlineспецифікатора на шаблоні не має ніякої різниці, тому що маркуєте ви шаблон inlineчи ні, це не має значення.
gnzlbg

34

Це не має значення. Усі шаблони вже є inline- не кажучи вже про те, що станом на 2012 рік inlineключове слово єдине використання - це зупинити компіляторів, які скаржаться на порушення ODR. Ви абсолютно правильні - ваш компілятор поточного покоління буде знати, що потрібно вкласти на власний розсуд, і, ймовірно, може це зробити навіть між підрозділами перекладу.


11
У стандарті не вказано, що всі шаблони вбудовані.
Себастьян Мах

16
@phresnel: Але шаблони мають таку саму семантику, як і inline-позначені функції (тобто декілька еквівалентних визначень можуть бути передані лінкеру, який вибере одне). Це, не інлінізуючи, є реальною функцією inlineключового слова.
Бен Войгт

2
@BenVoigt: Я знаю про значення ODR inline. Можливо, зазирніть на мою відповідь нижче (або вище, залежно від обраного сортування). Що стосується неспеціалізованих шаблонів, ви, звичайно, праві, але формально це не те саме.
Себастьян Мах

3
@DeadMG: в C ++ немає вимоги, що шаблон файлу повинен бути реалізований у файлі заголовка; її можна реалізувати в будь-якому місці. Для відображення цього я схильний рекомендувати позначити inlineте, що повинно бути вбудованим. Зазвичай це не має різниці, але в стандартах вони не однакові, і вони не всі вбудовані. Я приймаю вашу позицію щодо цього: "Це не має значення", але згідно стандарту, не всі шаблони є вбудованими, лише для вас як користувача C ++ вони виглядають так, ніби.
Себастьян Мах

7
Ваш коментар до прийнятої відповіді про те, що явна спеціалізація не є шаблоном (що, очевидно, після того, як про це сказали, звичайно ....), мабуть, найбільш корисна річ на цій сторінці. Ви не хотіли б додати його і до своєї відповіді?
Кайл Странд

6

Як ви запропонували, inlineце натяк на компілятор і нічого більше. Він може вибрати, щоб його ігнорувати або, власне, вбудовувати функції, не позначені вбудованим.

Використовуючи inlineшаблони, що використовувались (поганий) спосіб вирішення проблеми, кожен блок компіляції створив би окремий об'єкт для того ж шаблонного класу, який би викликав проблеми дублювання під час зв'язку. Використовуючи inline(я думаю) ім'я mangling виходить іншим, що обертається зіткненням імені під час зв’язку, але за рахунок сильно роздутого коду.  

Маршалл Клайн пояснює це тут краще, ніж я можу.


@Xeo: Це раніше не було. Перевірте тут: gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/… Я припускаю, що змінився останнім часом, тому я говорив у минулому часі.
Компонент 10 10

2
@Xeo: Чи можете ви вказати на частину стандарту, в якій сказано, що шаблони функцій завжди вбудовані? Бо їх немає.
Себастьян Мах

@phresnel: Цікаво, я можу поклястись, що прочитав це у стандарті. Можливо, я змішав це з тим, що шаблони функцій звільнені від ODR ( §14.5.5.1 p7 & p8). Мій поганий, я видалив неправильний коментар.
Xeo

@Component 10 Чому ви думаєте , що це поганий спосіб отримання випуску раунду компіляції
Капіл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.