Member class instantiation - c++

N4296::14.7.1/1 [temp.inst] told us the following:
The implicit instantiation of a class template specialization causes
the implicit instantiation of the declarations, but not of the
definitions, [...], member classes, [...]
What is that rule about? Let me give you an example:
template<class T>
class A
{
public:
template<class W> class Y; //1, declaration
template<class V> class U{ V v; }; //2, definition
};
A<int> a; //3, implicit instantiation
int main(){ }
Does implicit instantiation at //3 cause implicit instantiation at //2 and at //1? If so, what template argument was used to instantiate those member classes?

There is nothing special about those member templates, compared to the "outer" template. The compiler reads them as a declaration, such that it knows that there exist names as A<T>::Y<W> and A<T>::U<V>, much the same as when you declare the template for class A:
template <typename T>
class A {
int a;
};
Which also only declares the existence of a class A<T> but does not instantiate it.
Instantiation is deferred until a templated type is actually used (or explicitly instantiated), which equally applies to the member templates.

Related

A confusion about explicit specialization for member of class template

template<class T> struct A {
struct B { };
template<class U> struct C {
void show();
};
};
template<>
template<>
void A<int>::C<int>::show(){ //#1
}
int main(){
}
Consider the above code, At #1, it's an explicit specialization definition for member of member class template. Some rules will be applied to it as the following specified:
temp.expl.spec#5
A member of an explicitly specialized class is not implicitly instantiated from the member declaration of the class template; instead, the member of the class template specialization shall itself be explicitly defined if its definition is required. In this case, the definition of the class template explicit specialization shall be in scope at the point at which the member is defined. The definition of an explicitly specialized class is unrelated to the definition of a generated specialization. That is, its members need not have the same names, types, etc. as the members of a generated specialization. Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax. The same is true when defining a member of an explicitly specialized member class. However, template<> is used in defining a member of an explicitly specialized member class template that is specialized as a class template.
Firstly, what's explicitly specialized class? Does it refer to the entity which has explicit specialization declaration? It seems to it doesn't mean it, please look at the example in Explicitly specialized class part
template<> template<> class A<int>::B<double>;
According to that example, A<int> within the explicit specialization for member can be called a explicitly specialized class. So, In my first example A<int> and C<int> are all explicitly specialized class? I'm not sure. I feel the phrase explicitly specialized class is not clear in this section.
Please note the emphasized part, it means the enclosing class template explicit specialization shall appear in the same scope as that of explicit specialization definition for its member. The member is defined in global scope but there's no any explicit specialization definition for A<int> or C<int> that appears in the global scope. How to interpret this?
By the way, as a opposite example:
template<class T> struct A {
struct B { };
template<class U> struct C {
void show();
};
};
template<>
template<typename U>
struct A<int>::C{ //#2
void show();
};
template<>
template<typename U>
void A<int>::C<U>::show(){ //#3
}
int main(){
}
why such code is required an explicit specialization for class template C before #3, what's the difference between such two examples?
Explicitly specialized class
The phrase "explicitly specialized class" is unclear in this section,
temp.expl.spec#15
A member or a member template may be nested within many enclosing class templates. In an explicit specialization for such a member, the member declaration shall be preceded by a template<> for each enclosing class template that is explicitly specialized.
[ Example:
template<class T1> class A {
template<class T2> class B {
void mf();
};
};
template<> template<> class A<int>::B<double>;
template<> template<> void A<char>::B<char>::mf();
— end example ]
what's the explicitly specialized class mean, Is it refer to an entity that have a explicit specialization declaration or something others? It seems to no explicit specialization for A<int> in the above example.
There is no confusion there, you have to parse those statements (C++ and English) according to their grammatical structure. Source code is description of program in language understandable for humans. Programming language is a tool of human cooperation.
CWG529 removed need to understand intuitively by changing wording to explain order and content of template-ids.
Here you declared template of class A with template parameter T, which contains class B and a nested declaration of template class C with template parameter U, which contains a method show():
template<class T> struct A {
struct B { };
template<class U> struct C {
void show();
};
};
Here you declared, that for explicitly specialized template class A (which required to have it declared first) with T = int that there is a template class C which contains method show()
template<>
template<typename U>
struct A<int>::C{ //#2
void show();
};
This declaration doesn't contradict previous one, but because it's a specialization of class A, it may expand it! You can do this:
template<>
template<typename U>
struct A<int>::C{ //#4
void hide();
};
Which means that for any A with T=int, there is a template class C that got member hide(). But other A's will have template class C with member show(). What previous statement did that it removed any doubts about content of C for this A's specialization.
Now this only defines member function show() for all C's contained in A<int>:
template<>
template<typename U>
void A<int>::C<U>::show(){ //#3
}
You don't have an explicit specialization of C here, which is an enclosing class for show(). the memeber id show() is preceded by an unspecialized template-id template<typename U> ... C<U>. There is only a definition of member function but it requires a visible declaration of that template C - the #2 part. The visibility may be attained by various means and "the scope" mentioned is generalized description of it.
Omitting part #2 would be a semantic equivalent of writing:
class C;
void C::show() { // ill-formed - C is an incomplete type.
}
We would know that all of A's contain some class C, but we don't have a complete definition for that particular C in specialized A<int> (and it may be different).
This statement actually states that specialization C<int>nested in specialization A<int> contains show()
template<>
template<>
void A<int>::C<int>::show(){ //#1
}
Any possibility of contradiction, ambiguity or uncertainty (aside from undefined behavior) are leading to ill-formed code and rules are meant to form the framework of limitations against which the code should be checked. With absence of #2, the #3 at some point could be followed by #4, then the #3 statement would become illegal and thus it is deemed as such. #2 and #4 at same time would be two definitions of same thing which also leads either to ill-formed code if they are present in same unit, or they would lead to undefined behavior if they are present in separate units within program.

An Issue about the rule of explicit specialization where mentioned implicit instantiation

#include <iostream>
template<class T> struct A {
enum E : T;
};
template<class T> enum A<T>::E : T { eT };
template<> enum A<char>::E : char { //#1
echar
};
int main(){
}
Consider the above code which is mentioned in temp.expl.spec#6, it's a typically ill-formed code. The rule says:
If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.
At the point #1, where the specialization A<char> will cause implicit instantiation
As a contrast:
#include <iostream>
template<class T> struct A {
struct Test;
};
template<typename T>
struct A<T>::Test{
};
template<>
struct A<int>::Test{ //#2
int c;
};
int main(){
}
Consider this code, At the point #2, where the specialization A<int> also cause implicit instantiation, The difference of the implicit instantiation between such two codes is said as the following:
temp.inst#2
The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, default arguments, or noexcept-specifiers of the class member functions, member classes, scoped member enumerations, static data members, member templates, and friends; and it causes the implicit instantiation of the definitions of unscoped member enumerations and member anonymous unions. However, for the purpose of determining whether an instantiated redeclaration is valid according to [basic.def.odr] and [class.mem], a declaration that corresponds to a definition in the template is considered to be a definition.
Because in the first code, the member enumeration is unscoped, hence the implicit instantiation of A<char> will also implicit instantiated the definition for enum E. As a contrast, in the second, Test is a member class, hence the implicit instantiation of specialization A<int> will only cause implicit instantiation of the declaration for member class Test rather than definition.
As a variant case of the first code:
#include <iostream>
template<class T> struct A {
enum E : T;
};
template<> enum A<char>::E : char {
echar
};
template<> enum A<int>::E : int { //#1
echar
};
int main(){
}
The difference from the first code is that there's no definition for member enumeration E of its enclosing primary class template, within the primary class template A, it's just a declaration.
So, I think the rule in [temp.expl.spec#6] is not clear. As these above codes shown, in each case, the specialization of primary class template all cause the implicit instantiation for class member, The distinction is one expect the implicit instantiation of declaration , the other is definition.
So, I think modified the rule as the following:
If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation of the definition that instantiated from the definition for the corresponding entity, in every translation unit in which such a use occurs; no diagnostic is required.
It will be conform the observable result. If I miss something, please correct me.

Implicit instantiation depending on scoped or unscoped enumeration

14.7.3/6 says the following:
If a template, a member template or the member of a class template is explicitly specialized then that
specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the program is ill-formed, no diagnostic required. An implicit instantiation is never generated for an explicit specialization that is declared but not defined.
It then gives the following example:
template<class T> struct A
{
enum E : T;
enum class S : T;
};
template<> enum A<int>::E : int { eint }; // OK
template<> enum class A<int>::S : int { sint }; // OK
template<class T> enum A<T>::E : T { eT };
template<class T> enum class A<T>::S : T { cT };
template<> enum A<char>::E : char { echar }; // ill-formed, A<char>::E was instantiated
// when A<char> was instantiated
template<> enum class A<char>::S : char { schar }; // OK
I'm not following how it is able to compile the last line but not the one before it. I expected both examples to fail because both A<char>::E and A<char>::S were being implicitly instantiated. I notice when I remove class from the enum-key of S in the primary template the last line fails with the same message as the other. Why does this happen?
Implicit instantiation of a class template implicitly instantiates the definitions of unscoped member enumerations, but only the declarations of scoped member enumerations.
§14.7.1 [temp.inst]/p1 (emphasis added):
The implicit instantiation of a class template specialization causes
the implicit instantiation of the declarations, but not of the
definitions, default arguments, or exception-specifications of the
class member functions, member classes, scoped member
enumerations, static data members and member templates; and it
causes the implicit instantiation of the definitions of unscoped
member enumerations and member anonymous unions.

How to access template parameter from specialized member function?

#include <stdio.h>
template<typename T, int N>
class A
{
public:
void func();
};
template<typename T, int N>
void A<int, N>::func()
{
printf("%d\n", N);
}
int main()
{
A<int, 3> a;
a.func();
return 0;
}
When I try to compile this piece of code, g++ gives these errors:
test.cpp:10:22: error: invalid use of incomplete type ‘class A<int, N>’
test.cpp:4:7: error: declaration of ‘class A<int, N>’
I've only managed to compile this when A::func isn't specialized at all and when the function is also specialized for N.
How do I specialize A::func for T and access N (which should be able to be any value), too?
If this was possible, the syntax would have to be
template<int N>
void A<int, N>::func()
{
printf("%d\n", N);
}
I.e., T would not be mentioned in the template parameter list.
But unfortunately, it isn't possible. Individual functions (including member functions) cannot be partially specialized.
From the Standard (in the section about partial class template specializations):
(§14.5.5/2) Each class template partial specialization is a distinct template and definitions shall be provided for the members of a template partial specialization (14.5.5.3).
In your situation, the most direct way to accomplish what you need would therefore be to partially-specialize the entire class template:
template<int N>
class A<int,N>
{
public:
void func();
};
template<int N>
void A<int,N>::func()
{
printf("%d\n",3);
}
Working example of this on Coliru (Of course, the definition of func could be inlined into the class template definition.)
But this might not be optimal when the class template has many other members, since you would have to redefine them all:
(§14.5.5/3) [...] 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. Class template partial specialization members that are used in a way that requires a definition shall be defined; the definitions of members of the primary template are never used as definitions for members of a class template partial specialization. [...]
In some cases it is preferable to declare a separate class template with just this one function as member (possibly a static member, if no access to other members is required – possibly passing members to which access is required as explicit function arguments), and then refer to that from within the actual class template (to avoid having to partially-specialize the entire class template).

Templates :Name resolution:Point of instantiation: -->can any one tell some more examples for this statement?

This is the statement from ISO C++ Standard 14.6.4.1 Point of instantiation
For a function template specialization, a member function template
specialization, or a specialization for a member function or static
data member of a class template, if the specialization is implicitly
instantiated because it is referenced from within another template
specialization and the context from which it is referenced depends on a
template parameter, the point of instantiation of the specialization is
the point of instantiation of the enclosing specialization. Otherwise,
the point of instantiation for such a specialization immediately follows
the namespace scope declaration or definition that refers to the
specialization.
If a function template or member function of a class template is called in
a way which uses the definition of a default argument of that function
template or member function, the point of instantiation of the default
argument is the point of instantiation of the function template or member
function specialization.
For a class template specialization, a class member template specialization,
or a specialization for a class member of a class template, if the
specialization is implicitly instantiated because it is referenced from
within another template specialization, if the context from which the
specialization is referenced depends on a template parameter, and if the
specialization is not instantiated previous to the instantiation of the
enclosing template, the point of instantiation is immediately before the
point of instantiation of the enclosing template. Otherwise, the point of
instantiation for such a specialization immediately precedes the
namespace scope declaration or definition that refers to the specialization.
I am unable to write a programs for this whole section. I am trying to write a programs for this section from yesterday.
Can any one provide me a code for this sections to understand.
Please, normally ..I tried to ask a 1 or more points. In any section. But here iam unable to understand a single point in this section.
So, kindly can any one provide me a code(programs) for this sections to understand.
I find this quite mind-screwing, and the committee has more such fun. So I think it's likely I have some errors in the below. So please read it with care :)
Third paragraph
For a class template specialization, a class member template specialization, or a specialization for a class member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization, if the context from which the specialization is referenced depends on a template parameter, and if the specialization is not instantiated previous to the instantiation of the enclosing template, the point of instantiation is immediately before the point of instantiation of the enclosing template.
In other words, if a class template or a nested class of a class template is instantiated, and the context that causes that instantiation depends on a template parameter, the template/nested class is instantiated immediately before the point of instantiation of the template that refers to it.
The context in the other specialization can either depend on template parameters, which is the case for primary templates, partial specializations and members of a class template, or it does not depend on template parameters, which is the case for references from within explicit specializations.
Otherwise [i.e. the context is nondependent], the point of
instantiation for such a specialization immediately precedes the namespace scope declaration or definition that refers to the specialization.
This distinction is important. Consider what would happen if the point of instantiation for specializations from dependent contexts would preceede immediately to the namespace scope declaration or definition that refers to it
template<typename T, int N>
struct A {
typedef typename A<T, N-1>::type *type;
};
template<typename T>
struct A<T, 0> {
typedef T type;
};
typedef A<int, 2>::type ptr;
This template is supposed to add N pointer declarators. So A<int, 2> is int** for example.
The context around typedef A<int, 2>::type is non-dependent, so A<int, 2> is instantiated before the typedef declaration.
Within A<int, 2>, we have A<int, N-1>::type, which appears in a dependent context and which references A<int, 1>::type. So the Standard requires us to instantiate A<int, 1> at the same point we instantiated A<int, 2>.
If we would instantiate this immediately before the namespace scope declaration that referred to it (before the primary template definition), we would not notice the partial specialization A<T, 0> when processing `A<int, N-1>::type within A<int, 1> because we would instantiate A<int, 1> before that specialization.
Second paragraph
This is just so that names looked up in default arguments are consistent with names looked up in the rest of the function that they are used for (i.e their POI is the same as the POI of their function template / member function of class template).
First paragraph
This is basically the same as the third paragraph. However, function templates are instantiated after the entity that refer to them so that recursive uses are possible, like in the following example. In contrast, class templates are instantiated before the entity that refer to them because the entity required that class type to be complete. If the class type's POI would be after that entity, the class type would still be non-existent.
template<typename T>
void f(T);
template<typename T>
struct A {
void g() {
f(0);
}
void h() { /* do a dance */ }
};
template<typename T>
void f(T t) {
A<T> a;
a.h();
}
void g() {
A<int> a;
a.g();
}
If f would be instantiated before A<int>, then it could not access a.h() because at that point it did not exist yet. Therefor, function templates are instantiated after the entity that refer to them, and class templates are instantiated before the entity that refer to them.
Request some one to correct my understanding...
I think the code below illustrates what 1 and 2 mean (from what I have understood):
template<class T> void f1(T t){cout << 0;}
template<class T> void f2(T t, void (*p)(int) = f1){
(*p)(0);
}
void f(double d){cout << 1;}
template<class T> void g(T t){
f1(t); // this is the interesting call.
}
void f1(int t){cout << 2;}
int main(){
g(2);
f2(2);
} // POI for f1(t), Also POI for f2(2)
Consider the call g(2). At the POI, there are basically three overloads (viable) that are visible:
function template
f(int)
f(double).
The call however routs to 'f(int)' as this is the best match.
In the same way, the POI for 'f2(2)' is the closing brace of main. The default argument 'f1' is once again looked up from this POI and resolves to 'f1(int)' which is the best match of all the three overloads available.
Thanks #litb. Revised after #litb corrected my understanding:
double f1(double d){cout << 1; return 0.0;}
template<class T> void f2(T t1, T t2 = f1(T())){}
template<class T> void g(T t){
f1(t); // this is the interesting call.
}
struct A{
friend A f1(A const &){cout << 2; return A();}
};
int main(){
g(A()); // 'f1(t)' resolves to friend function declaration
f2(A()); // The call to 'f1' in default argument also resolves to friend
// function declaration
// This is because for non dependent names, only ADL is performed
// at POI which is at closing brace of main.
} // POI for f1(t), Also POI for f2(2) in that order
Remember that in both the above calls, there are two overloads that are candidates. The namspace function 'f1(double)' and the friend function 'f1' declaration (found due to ADL). Since this is the only viable function, the calls resolve to the friend declaration 'f1'.
I think Point 3 means this:
template<class A> struct T{
T(int x = 0){}
};
template<class A> struct U{
U():t(f(A())){}
T<A> t;
}; // POI of 'gt' instantiation
T<int> gt(f(2)); // At this point 'f' is not found, hence error
int f(int x){return x;}
int main(){
U<int> u;
} // There are 2 POIs here 'U<int>::T<int>' and 'U<int>' and in that order
// Therefore 'f' is visible from here.