Шаблоны не подразумевают inline



Дисклеймер: в этом посте слово "специализация" будет значить конкретную программную сущность, объявленную через template<> с пустыми треугольными скобками, которая переопределяет поведения шаблона для конкретного типа.



В прошлом посте кратко коснулись этого. Сегодня разберемся в этом подробнее.



Мы уже знаем, что в программе может быть больше одного определения шаблона и это нормально. Ровно также может быть больше одного определения inline сущности. Так есть ли между этими утверждениями связь?



Очевидно, классы не могут быть inline. Разговор здесь пойдет только про inline функции и переменные(с С++14).



Во-первых, стандарт ничего не говорит по поводу того, что шаблоны по умолчанию inline. Хотя, например, для constexpr функций и статических полей класса это явно описано.



Во-вторых, в нем есть пара слов про явные специализации



Whether an explicit specialization of a function or variable template is inline, 

constexpr, constinit, or consteval is determined by the explicit specialization and

is independent of those properties of the template. Similarly, attributes appearing

in the declaration of a template have no effect on an explicit specialization of that

template...





Эта строчка говорит нам о том, что спецификаторы, которыми помечены явные специализации, могут не совпадать со спецификаторами самих шаблонов. Значит, что шаблоны имеет смысл помечать inline и мы даже может можем изменить это поведение в явной специализации. А значит, шаблоны не подразумевают inline. Их поведение только лишь схоже с inline сущностими в плане обхода ODR. Пример из стандарта:



template<class T> void f(T) { /* ... */ } 

template<class T> inline T g(T) { /* ... */ }



template<> inline void f<>(int) { /* ... */ } // OK, inline

template<> int g<>(int) { /* ... */ } // OK, not inline





Здесь нужно быть аккуратным, потому что на явные специализации распространяется ODR. Явные специализации - уже не шаблоны, поэтому, если вы хотите поместить их в хэдэр, то нужно помечать их inline, чтобы линковщик не ругался.



Если инлайн в нынешнее время в основном используется для обхода ODR, то есть ли смысл помечать шаблонные функции этим ключевым словом?



Особого смысла нет(помимо явных специализаций). Темплейты и так не подвержены ODR. А в остальном инлайн только лишь указывает компилятору, чтобы он сделал проверку на возможность inline expansion. Но он в принципе и так это делает для всех функций.



Differentiate things apart. Stay cool.



#template #cppcore #cpp14 #compiler