This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 114a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-04-18


69. Storage class specifiers on template declarations

Section: 9.2.2  [dcl.stc]     Status: TC1     Submitter: Mike Ball     Date: 17 Oct 1998

Mike Ball: I cannot find anything in the standard that tells me the meaning of a storage-class-specifier on a function template declaration. In particular, there is no indication what effect, if any, it has on the storage class of the instantiations.

There is an explicit prohibition of storage-class-specifiers on explicit specializations.

For example, if we have

    template<class T> static int foo(T) { return sizeof(T); }
does this generate static functions for all instantiations? By 9.2.2 [dcl.stc] the storage class applies to the name declared in the declarator, which is the template foo, not an instantiation of foo, which is named with a template-id. There is a statement in clause 14 that template names have linkage, which supports the contention that "static" applies to the template, not to instantiations.

So what does the specifier mean? Lacking a direct statement in the standard, I see the following posibilities, in my preference order.

  1. storage-class-specifiers have no meaning on template declarations, their use being subsumed by "export" (for the template name) and the unnamed namespace (for instantiations)
  2. storage-class-specifiers have no effect on the template name, but do affect the linkage of the instantiations, though this now applies linkage to template-ids, which I can find no support for. I suspect this is what was intended, though I don't remember
Of course, if anybody can find some concrete statement, that would settle it.

From John Spicer

The standard does say that a namespace scope template has external linkage unless it is a function template declared "static". It doesn't explicitly say that the linkage of the template is also the linkage of the instantiations, but I believe that is the intent. For example, a storage class is prohibited on an explicit specialization to ensure that a specialization cannot be given a different storage class than the template on which it is based.

Mike: This makes sense, but I couldn't find much support in the document. Sounds like yet another interpretation to add to the list.

John: Agreed.

The standard does not talk about the linkage of instantiations, because only "names" are considered to have linkage, and instances are not really names. So, from an implementation point of view, instances have linkage, but from a language point of view, only the template from which the instances are generated has linkage.
Mike: Which is why I think it would be cleaner to eliminate storage class specifiers entirely and rely on the unnamed namespace. There is a statement that specializations go into the namespace of the template. No big deal, it's not something it says, so we live with what's there.

John: That would mean prohibiting static function templates. I doubt those are common, but I don't really see much motivation for getting rid of them at this point.

"export" is an additional attribute that is separate from linkage, but that can only be applied to templates with external linkage.
Mike: I can't find that restriction in the standard, though there is one that templates in an unnamed namespace can't be exported. I'm pretty sure that we intended it, though.

John: I can't find it either. The "inline" case seems to be addressed, but not static. Surely this is an error as, by definition, a static template can't be used from elsewhere.

Proposed resolution (10/00):

Change the text in Clause 13 [temp] paragraph 4 from:
A template name may have linkage (6.6 [basic.link]).
to:
A template name has linkage (6.6 [basic.link]). A non-member function template can have internal linkage; any other template name shall have external linkage. Entities generated from a template with internal linkage are distinct from all entities generated in other translation units.