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

2025-04-13


2848. Omitting an empty template argument list for explicit instantiation

Section: 13.9.3  [temp.explicit]     Status: DRWP     Submitter: Anoop Rana     Date: 2024-01-15

[Accepted as a DR at the March, 2024 meeting.]

(From submission #489.)

Subclause 13.9.3 [temp.explicit] paragraph 8 specifies:

A trailing template-argument can be left unspecified in an explicit instantiation of a function template specialization or of a member function template specialization provided it can be deduced (13.10.3.7 [temp.deduct.decl]). If all template arguments can be deduced, the empty template argument list <> may be omitted. [Example 3:
 template<class T> class Array { /* ... */ }; template<class T> void sort(Array<T>& v) { /* ... */ } // instantiate sort(Array<int>&) -- template-argument deduced template void sort<>(Array<int>&); 
end example]

This paragraph is redundant with a more general provision on explicitly specifying template arguments in 13.10.2 [temp.arg.explicit] paragraph 4:

Trailing template arguments that can be deduced (13.10.3 [temp.deduct]) or obtained from default template-arguments may be omitted from the list of explicit template-arguments. [Note 1: A trailing template parameter pack (13.7.4 [temp.variadic]) not otherwise deduced will be deduced as an empty sequence of template arguments. —end note] If all of the template arguments can be deduced or obtained from default template-arguments, they may all be omitted; in this case, the empty template argument list <> itself may also be omitted. ...

A similar duplication is in 13.9.4 [temp.expl.spec] paragraph 10.

Proposed resolution (approved by CWG 2024-02-16):

  1. Change the example in 13.9.3 [temp.explicit] paragraph 4 as follows:

     ... template<class T> void sort(Array<T>& v) { /* ... */ } template void sort(Array<char>&); // argument is deduced here (13.10.2 [temp.arg.explicit]) ... 
  2. Remove 13.9.3 [temp.explicit] paragraph 8:

    A trailing template-argument can be left unspecified in an explicit instantiation of a function template specialization or of a member function template specialization provided it can be deduced (13.10.3.7 [temp.deduct.decl]). If all template arguments can be deduced, the empty template argument list <> may be omitted. [Example 3:
     template<class T> class Array { /* ... */ }; template<class T> void sort(Array<T>& v) { /* ... */ } // instantiate sort(Array<int>&) -- template-argument deduced template void sort<>(Array<int>&); 
    end example]
  3. Change the example in 13.9.4 [temp.expl.spec] paragraph 1 as follows:

    ... [ Example:
     template<class T> class stream; template<> class stream<char> { /* ... */ }; // #1 template<class T> class Array { /* ... */ }; template<class T> void sort(Array<T>& v) { /* ... */ } template<> void sort<int>(Array<int>&); // #2 template<> void sort<char*>(Array<char*>&); // #3 template argument is deduced (13.10.2 [temp.arg.explicit]) ... 
    Given these declarations, stream<char>#1 will be used as the definition of streams of chars; other streams will be handled by class template specializations instantiated from the class template. Similarly, #2 will be used as the sort function for arguments of type Array<int> and #3sort<char*> will be used as the sort function for arguments of type Array<char*>; other Array types will be sorted by functions generated from the function template. —end example]
  4. Remove 13.9.4 [temp.expl.spec] paragraph 10:

    A trailing template-argument can be left unspecified in the template-id naming an explicit function template specialization provided it can be deduced (13.10.3.7 [temp.deduct.decl]). [Example 6:
     template<class T> class Array { /* ... */ }; template<class T> void sort(Array<T>& v); // explicit specialization for sort(Array<int>&) // with deduced template-argument of type int template<> void sort(Array<int>&); 
    end example]


close