What does template's implicit specialization mean? - c++

In the chapter N3797::14/4 [temp] (emphasis mine)
A template name has linkage (3.5). A non-member function template can
have internal linkage; any other template name shall have external
linkage. Specializations (explicit or implicit) of a template that
has internal linkage are distinct from all specializations in other
translation units.
was mentioned about implicit specialization. As far as I understand from the context, that concept is different from the template explicit specialization which has
template < > declaration
grammar. So, I'm guessing that implicit specialization has something to do with a partial class template specialization. Unfortunately, I couldn't normative reference defining the implicit specialization concept in the current working draft.

There is no normative term called "implicit specialization".
However, I believe that in this context, it means the complement of "explicit specialization": Every specialization that was not explicitly specialized by the user, in other (normative) words, instantiated specializations.
Consider that there are
Explicit specializations
Implicit instantiations
Explicit instantiations
Specializations instantiated through the latter two one could refer to as "implicit specializations".

The term isn't used much in the Standard, but we can deduce what it means from §14.5.5.3 - reproduced below - which I've broken into paragraphs (A), (B) and (C) for ease of reference (boldfacing mine):
(A) If a member template of a class template is partially specialized, the member template partial specializations are member templates of the enclosing class template; if the enclosing class template is instantiated (14.7.1, 14.7.2), a declaration for every member template partial specialization is also instantiated as part of creating the members of the class template specialization.
(B) If the primary member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the partial specializations of the member template are ignored for this specialization of the enclosing class template.
(C) If a partial specialization of the member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the primary member template and its other partial specializations are still considered for this specialization of the enclosing class template. [ Example:
template<class T> struct A {
template<class T2> struct B {}; // #1
template<class T2> struct B<T2*> {}; // #2
};
template<> template<class T2> struct A<short>::B {}; // #3
A<char>::B<int*> abcip; // uses #2
A<short>::B<int*> absip; // uses #3
A<char>::B<int> abci; // uses #1
-- end example]
Repeating (B) with my cross-references to the example in parentheses:
"if the primary member template (i.e. #1) is explicitly specialised (as at #3) for a given (implicit) specialisation of the enclosing class template (A), the partial specialisations of the member template (#2) are ignored for this specialisation of the enclosing class template".
We see the specialisation at #3 results in the ignoring of #2 for absip;. We can therefore conclude that the following line...
template<> template<class T2> struct A<short>::B {}; // #3
...performs an implicit specialisation of the enclosing class template, namely A<short>.
So, implicit specialisation is when specialisation of a member function implicitly involves specialisation of the class template that it's a member of. Put another way, the class template A didn't require a separate earlier specialisation for short before the member template at #1 was specialised, because it could be specialised implicitly.

Related

C++ wording for template explicit specialization

If we consider function template overloading, the standard behaviour in C++ is to first choose the "most specialized" overload (out of the base templates). The next step is to see if the chosen overload is explicitly specialized. If it is, the explicit specialization that matches will be chosen.
Could you point to the place in the standard that defines the second step (the highlighted part in the previous paragraph)?
Thank you.
If I understand you correctly then perhaps you were referring to this from [temp.inst§4]:
Unless a function template specialization has been explicitly instantiated or explicitly specialized, the function template
specialization is implicitly instantiated when the specialization is
referenced in a context that requires a function definition to exist
or if the existence of the definition affects the semantics of the
program [...]
Which, by way of negation, says that the explicit specialization gets the precedence.
From the working draft (N4713):
17.6.6.2 Partial ordering of function templates [temp.func.order]
1. If a function template is overloaded, the use of a function template specialization might be ambiguous because template argument deduction may associate the function template specialization with more than one function template declaration. Partial ordering of overloaded function template declarations is used in the
following contexts to select the function template to which a function template specialization refers:
(1.1) — during overload resolution for a call to a function template specialization;
(1.2) — when the address of a function template specialization is taken;
(1.3) — when a placement operator delete that is a function template specialization is selected to match a placement operator new;
(1.4) — when a friend function declaration, an explicit instantiation or an explicit specialization refers to a function template specialization.
Also:
2 Partial ordering selects which of two function templates is more specialized than the other by transforming
each template in turn (see next paragraph) and performing template argument deduction using the function
type. The deduction process determines whether one of the templates is more specialized than the other.
If so, the more specialized template is the one chosen by the partial ordering process. If both deductions
succeed, the partial ordering selects the more constrained template as described by the rules in 17.4.4.
17.6.5.2 Partial ordering of class template specializations [temp.class.order]
1 For two class template partial specializations, the first is more specialized than the second if, given the following rewrite to two function templates, the first function template is more specialized than the second
according to the ordering rules for function templates (17.6.6.2):
(1.1) — Each of the two function templates has the same template parameters and associated constraints (17.4.2) as the corresponding partial specialization.
(1.2) — Each function template has a single function parameter whose type is a class template specialization where the template arguments are the corresponding template parameters from the function template
for each template argument in the template-argument-list of the simple-template-id of the partial specialization.
2 [ Example:
template<int I, int J, class T> class X { };
template<int I, int J> class X<I, J, int> { }; // #1
template<int I> class X<I, I, int> { }; // #2
template<int I0, int J0> void f(X<I0, J0, int>); // A
template<int I0> void f(X<I0, I0, int>); // B
template <auto v> class Y { };
template <auto* p> class Y<p> { }; // #3
template <auto** pp> class Y<pp> { }; // #4
template <auto* p0> void g(Y<p0>); // C
template <auto** pp0> void g(Y<pp0>); // D
According to the ordering rules for function templates, the function template B is more specialized than the function template A and the function template D is more specialized than the function template C.
Therefore, the partial specialization #2 is more specialized than the partial specialization #1 and the partial specialization #4 is more specialized than the partial specialization #3. —end example ]
[ Example:
template<typename T> concept C = requires (T t) { t.f(); };
template<typename T> concept D = C<T> && requires (T t) { t.f(); };
template<typename T> class S { };
template<C T> class S<T> { }; // #1
template<D T> class S<T> { }; // #2
template<C T> void f(S<T>); // A
template<D T> void f(S<T>); // B
The partial specialization #2 is more specialized than #1 because B is more specialized than A. —end example ]
The standard does not define formally what an explicit specialization is. The most relevant part I can find is the example in [temp.expl.spec]/1:
[ Example:
template<class T> class stream;
template<> class stream<char> { /* ... */ };
template<class T> class Array { /* ... */ };
template<class T> void sort(Array<T>& v) { /* ... */ }
template<> void sort<char*>(Array<char*>&);
Given these declarations, stream<char> 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, sort<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 template. — end example ]

C++ standard paragraph about member template specialization of unspecialized template

In the current draft of the C++ standard, the paragraph [temp.expl.spec]p.18 says:
A specialization of a member function template, member class template, or static data member template of a non-specialized class template is itself a template.
However, the above paragraph temp.expl.spec]p.17 states (my emphasis):
In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well. [...]
Therefore, it should be impossible to explicitly specialize a member template without specializing its enclosing class template, so [temp.expl.spec]p.18 is wrong. I highlighted the word explicitly because [temp.expl.spec]p.18 says "A specialization [...]". Specialization can have a lot of meanings, one of which could be explicit specialization.
I checked and [temp.expl.spec]p.18 appeared in the standard before [temp.expl.spec]p.17. For example, in the 1996 version of the standard [temp.expl.spec]p.18 is present while [temp.expl.spec]p.17 is not.
What is the original intended meaning of [temp.expl.spec]p.18?
Thank you.
There can be partial specialization of a member class template of a non-specialized class template.
Your point 17 prohibits full specialization of such a member; and point 18 clarifies that the partial specialization in this case is still a template.
The terminology "explicitly specialize" means fully specialize, and excludes partial specialization.
template<typename T>
struct A
{
template<typename U, typename V>
struct B
{
void f() {}
};
};
// OK: Partially specialize A<T>::B. This is a template
template<typename T>
template<typename U>
struct A<T>::B<U, int>
{
void g() {}
};

Why is in-class partial specialization well-formed?

According to [temp.class.spec] 5/ (emphasis mine)
A class template partial specialization may be declared or redeclared
in any namespace scope in which the corresponding primary template may
be defined
This would suggest that partial specialization (just like in case of explicit specialization) have to appear in the namespace scope. This is actually confirmed by the example below the paragraph:
template<class T> struct A {
struct C {
template<class T2> struct B { };
};
};
// partial specialization of A<T>::C::B<T2>
template<class T> template<class T2>
struct A<T>::C::B<T2*> { };
//...
A<short>::C::B<int*> absip; // uses partial specialization
On the other hand C++ Standard Core Language Active Issues No 727 example suggests that in-class partial specialization is well formed:
struct A {
template<class T> struct B;
template <class T> struct B<T*> { }; // well-formed
template <> struct B<int*> { }; // ill-formed
};
I'm sure core issues document is correct here, but cannot find appropriate reference to confirm that. Can you help me?
The intent is that it is valid—see N4090:
Following a brief discussion of DR 17557 and DR 7278 in Issaquah 2014, and based on discussion on the core-reflector91011, it seems as if Core is converging on the following rules for member templates and their specializations: Partial specializations and explicit specializations can be first
declared at either innermost-enclosing-class scope or enclosing
namespace scope (recognizing that explicitly declaring specializations
does not constitute adding members to a class and hence can be done
after the closing brace).
7 http://www.open­std.org/jtc1/sc22/wg21/docs/cwg_toc.html#727
8 http://www.open­std.org/jtc1/sc22/wg21/docs/cwg_toc.html#1755
9 http://accu.org/cgi­bin/wg21/message?wg=core&msg=24366(24033, 24290, 24309, 24368)
10 http://accu.org/cgi­bin/wg21/message?wg=core&msg=24731(24731, 24732, 24736, 24738)
11 http://accu.org/cgi­bin/wg21/message?wg=core&msg=25168 (25168­-25179)
I filed a core issue, because I feel the current wording is not clear enough; the paragraph you quoted can be interpreted to disallow in-class partial specializations.
The spec says at 14.5.2p1
A template can be declared within a class or class template; such a template is called a member template.
And at 14.5.5p2
Each class template partial specialization is a distinct template and definitions shall be provided for the members of a template partial specialization
Therefore, a class template partial specialization is a template, which is natural aswell because it still has parameters that are not fixed, therefore it denotes a "family of classes". And templates can be declared within a class or class template.

Template struct with the default template argument is not instantiated

Let's say I have this code
template<typename T2, typename T = int>
struct X
{
static double f;
};
template<typename T>
double X<T>::f = 14.0;
If I try to compile clang give me the following error
nested name specifier 'X::' for declaration does not refer into a
class, class template or class template partial specialization
and for GCC :
error: template definition of non-template 'double X::f'
The question is :
Why the compiler want us to specialize the struct X like that :
template<typename T2>
struct X<T2,int>
{
static double f;
};
The first declaration has int as a default argument, why the compiler don't choose this declaration ?
I searched in the standard anchor [temp.spec] but it didn't help.
I ask this question after answered this one on SO.
Thanks for your help !
"Why the compiler want us to specialize the struct X like that" - that's not what the error messages are saying. You don't need to do this, and you really shouldn't do it unless what you want is a partial specialization and a static member defined only for that partial specialization.
The problem is that template<typename T2, typename T = int> struct X is a class template that has two template parameters. The fact that the second one has a default template argument doesn't change the fact that there are still two parameters.
So, you need to define your class template member as belonging to a class template with two parameters, like this:
template<typename T2, typename T>
double X<T2, T>::f = 14.0;
The relevant paragraphs in the standard (N4527, the current draft):
[14.5.1p3]
When a member function, a member class, a member enumeration, a static
data member or a member template of a class template is defined
outside of the class template definition, the member definition is
defined as a template definition in which the template-parameters are
those of the class template. The names of the template parameters used
in the definition of the member may be different from the template
parameter names used in the class template definition. The template
argument list following the class template name in the member
definition shall name the parameters in the same order as the one used
in the template parameter list of the member. Each template parameter
pack shall be expanded with an ellipsis in the template argument list.
[14.1p9]
[...] A default template-argument shall not be specified in the
template-parameter-lists of the definition of a member of a class
template that appears outside of the member’s class. [...]
As specified in the quote above, the actual names of the template parameters (T2 and T) don't matter, they can be different from the ones in the class template definition, but they need to be consistent within the definition of the member. That is, you can do this
template<typename T, typename U>
double X<T, U>::f = 14.0;
and it will still define the member of the correct X class template. However, using the same names can make things easier to understand when reading the code.
By defining the partial specialization before the definition of f in your original example, template<typename T> double X<T>::f = 14.0; becomes a valid definition of the member f of the partial specialization template<typename T2> struct X<T2,int>, and only of that template (partial specializations are templates themselves). The member f of the primary template template<typename, typename> struct X remains undefined.
The relevant wording is in [14.5.5.3p1]:
The template parameter list of a member of a class template partial
specialization shall match the template parameter list of the class
template partial specialization. The template argument list of a
member of a class template partial specialization shall match the
template argument list of the class template partial specialization. A
class template specialization is a distinct template. The members of
the class template partial specialization are unrelated to the members
of the primary template. [...]

Implicit instantiation of the template within its own definition

Let's consider simple example about template implicit instantiation:
#include <iostream>
template<int N>
class A
{
static const int a = A<N-1>::a; //1, OK, doesn't require implicit intantiation
};
template<int N>
class B
{
static const int a = B<1>::a; //2, Error, implicit instantiation of template 'B<1>' within its own definition
};
int main(){ }
DEMO
The standard wasn't clear about that fact. What it says is only that N3797::14.7.1/1 [temp.inst]:
Unless a class template specialization has been explicitly
instantiated (14.7.2) or explicitly specialized (14.7.3), the class
template specialization is implicitly instantiated when the
specialization is referenced in a context that requires a
completely-defined object type or when the completeness of the class
type affects the semantics of the program.
Neither 1 nor 2 don't require the class type to be completely defined, however the second one causes the error about implicit instantiation. I'd like to understand why.
I think the reason B<1> fails immediately and A<N-1> not is because of temp.res#general-8.4
The validity of a template may be checked prior to any instantiation. The program is ill-formed, no diagnostic required, if:
a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter