This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
[Accepted as a DR at the November, 2022 meeting.]
It is unclear whether an explicit template specialization "inherits" the attributes written on the primary template, or whether the specialization has to repeat the attributes. For example:
template <typename Ty>
[[noreturn]] void func(Ty);
template <>
void func<int>(int) {
// Warning about returning from a noreturn function or not?
}
A similar question arises for attributes written on the parameters of the primary function template. For example:
template <typename Ty>
void func([[maybe_unused]] int i);
template <>
void func<int>(int i) {
// i is not used, should it be warned on or not?
}
There is implementation divergence for the example.
Suggested resolution [SUPERSEDED]:
Change in 13.9.4 [temp.expl.spec] paragraph 13 as follows:
Any attributes applying to any part of the declaration of an explicit specialization of a function or variable template, as well asWhetherwhether such an explicit specializationof a function or variable templateis inline, constexpr, or an immediate function, is determined by the explicit specialization and is independent of those properties of the template. [ Note: Attributes that would affect the association of the declaration of an explicit specialization with the declaration of the primary template need to match. -- end note ]
Proposed resolution (approved by CWG 2022-11-09):
Change 13.9.4 [temp.expl.spec] paragraph 13 as follows:
Whether an explicit specialization of a function or variable template is inline, constexpr, or an immediate function 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. [Example 7: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 template<typename> [[noreturn]] void h([[maybe_unused]] int i); template<> void h<int>(int i) { // Implementations are expected not to warn that the function returns but can // warn about the unused parameter. }—end example]