where's the point of instantiation of static data member template specialization - c++

Consider the below code:
#include <iostream>
template<typename T>
struct Test{
template<typename U>
static U value;
};
template<typename T>
template<typename U>
U Test<T>::value = U{};
//#1
int main(){
auto d = Test<int>::value<int>;
}
//#2
The [temp.point] section in the standard covers the most case of where the point of instantiation shall place. However I think it's unclear about static data member template, due to:
temp.point#1
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.
temp.point#4
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.
Two paragraphs all respectively cover the case they mentioned, they are a specialization for static data member of a class template and a class member template specialization, So, the specialization for static data member template could be called a specialization for static data member of a class template or a class member template specialization? I prefer to consider it as a class member template specialization, My reason is in the first paragraph, it has mentioned a member function template specialization, that implies if A is a specialization for X template, it would call it a X template specialization, however It's just my inference.
In the section of [temp.static], it implies that a static data member and static data member template are collectively called static data member of class or class template.
temp.static#1
A definition for a static data member or static data member template may be provided in a namespace scope enclosing the definition of the static member's class template.
[Note: A specialization of a static data member template is a static data member. A specialization of a member function template is a member function. A specialization of a member class template is a nested class.  — end note]
Now, the wording makes the question more unclear. So according to the above rules, Is the point of instantiation for Test<int>::value<int> is at #2 or #1?
If the POI of Test<int>::value<int> is at #2, then it will be considered as a specialization for static data member of a class template, otherwise if it's at #1, then it will be considered as a class member template specialization, I don't know which the position is correct. If I miss something, please correct me.

You may be confusing instantiation/specialization
template<typename T>
template<typename U>
U Test< T >::value = 88; // <- this is not specialization
template<>
template<>
int Test< int >::value<int> = 98; // <- this is specialization
Run this code https://godbolt.org/z/h434eG, take a look at the order of the numbers on the output, then uncomment the block with a specialization and run again.

The point of Cleiton Santoia Silva is that there is no explicit member template specialisation.
But if you read temp.inst#3:
Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
We still get a specialization which is triggered by the template usage in main. I would say to "virtual specialization", because it is not visible in the code. This results exaclty like if there would be an explicit specialization.
But the question is where would the compiler write this specialization - which is defined in [temp.point]. But by which paragraph? If you read carefully paragraph 4 you can see it has an additional condition (the otherwise is related to the inner / second if):
...if the specialization is implicitly instantiated because it is
referenced from within another template specialization, if the context from which the specialization is
Is the member function template referenced by the class template "Test"? No, it is only referenced inside main. So, we don't need to look at this paragraph.
But let us look at the first paragraph. There we have nearly the same condition just without "if" but "and":
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
Because the condition is not true we need to look at the "else case":
... Otherwise, the point of instantiation for such a specialization immediately follows the namespace scope declaration or definition that refers to the specialization.
This sentence is somehow misleading. What is a namespace scope declaration (I found no definition in the standard)? And which definition is meant here? Your interpretation was that the definition is meant where the template instanciation occured (main). But I don't think so. I Think definition of the template is meant.
So to answer your question: it should be before main (after main would make the program "ill-formed"). But you are right the wording should be improved there.
Btw:
You can have a "look inside a C++ compiler" by using cppinsights (here). Unfortunately it seems to work not correctly (in that case) for the implicit global namespace scope. Here you can see where the specializations are "practically" instantiated.
Old Answer
Cleiton Santoia Silva is totally right. Your source code shows just a static template member declaration and a static template member definition. It is no specialization.
Look here
The template instation happens here:
#include <iostream>
template<typename T>
struct Test{
template<typename U>
static U value; //this is a static member template declaration
};
template<typename T>
template<typename U>
U Test<T>::value = U{}; //this is a static member template definition
//this is a partial specialization of a template member variable
template<>
template<typename U>
U Test<char>::value = 42;
//this is a full specialization of a template member variable
template<>
template<>
int Test<int>::value<int> = 22;
int main()
{
auto d = Test<int> //<- here is Test<int> implicitly instantiated
::value<int>; //<- here is the member template ::Test<int>::value<int> implicitly instantiated
std::cout << Test<char>::value<int> << "\n"; //this prints 42
std::cout << Test<int>::value<int> << "\n"; //this prints 22
std::cout << Test<bool>::value<bool> << "\n"; //this prints 0
}
If you would write this - your program becomes ill-formed:
#include <iostream>
template<typename T>
struct Test{
template<typename U>
static U value; //this is a static member template declaration
};
template<typename T>
template<typename U>
U Test<T>::value = U{}; //this is a static member template definition
int main()
{
auto d = Test<int> //<- here is Test<int> instantiated
::value<int>; //<- here is the member template instantiated
std::cout << Test<char>::value<int> << "\n"; //this prints 42
std::cout << Test<int>::value<int> << "\n"; //this prints 22
std::cout << Test<bool>::value<bool> << "\n"; //this prints 0
}
//this is a partial specialization of a template member variable
template<>
template<typename U>
U Test<char>::value = 42;
//this is a full specialization of a template member variable
template<>
template<>
int Test<int>::value<int> = 22;
But this would be fine. Non inline static member definitions must defined in cpp files to not violate ODR.
But like with all templates - every template definition must be available in all translations units. This is reason why such a definition is usually definied in a header:
#include <iostream>
template<typename T>
struct Test{
template<typename U>
static U value; //this is a static member template declaration
};
//this is a partial specialization of a template member variable
template<>
template<typename U>
U Test<char>::value = 42;
//this is a full specialization of a template member variable
template<>
template<>
int Test<int>::value<int> = 22;
int main()
{
auto d = Test<int> //<- here is Test<int> implicitly instantiated
::value<int>; //<- here is the member template ::Test<int>::value<int> implicitly instantiated
std::cout << Test<char>::value<int> << "\n"; //this prints 42
std::cout << Test<int>::value<int> << "\n"; //this prints 22
std::cout << Test<bool>::value<bool> << "\n"; //this prints 0
}
template<typename T>
template<typename U>
U Test<T>::value = U{}; //this is a static member template definition

Related

c++ explicit specialization can not access primay template member but can access partial specialization member?

#include <iostream>
using namespace std;
template<class T, int I> // primary template
struct A {
void f(); // member declaration
};
template<class T, int I>
void A<T,I>::f() { } // primary template member definition
// partial specialization
template<class T>
struct A<T,2> {
void f();
void g();
void h();
};
// member of partial specialization
template<class T>
void A<T,2>::g() {
cout << "partial g()" << endl;
}
template<class T>
void A<T,2>::h() {
cout << "partial h()" << endl;
}
// explicit (full) specialization
// of a member of partial specialization
template<>
void A<char,2>::h() {
cout << "explicit h()" << endl;
}
int main() {
A<char,2> a2;
a2.f(); // ERROR, partial can not access primary member
a2.g(); // OK, uses partial specialization's member definition
a2.h(); // OK, explicit h() being called.
}
I went thorugh cpp reference, It says
"Members of partial specializations are not related to the members of
the primary template."
So understandably, a2 can not access member of primary specialization a2.f() ?
My Questions are
how is the relationship between member of partial specialization and member of explicit specialization ?
Why a2 can access the member of partial specialization a2.g() here ?
It is important to realize that a class template is not a class, but only a blueprint for one.
A<char,2> matches the specialized blueprint, so it has f,g,h member functions. Contents of the primary template are completely ignored.
Because A is a template class, its methods are instantiated only when actually called and only for those concrete template arguments because instantiation of A is a class, thus it has only one set of methods.
Since you did not define any A<char,2>::f, the linker reports undefined reference error.
There is a definition of A<char,2>::g available by instantiating template<class T> void A<T,2>::g() function - that is an ordinary method, not a function template.
For the same reason, A<char,2>::h also compiles - there is a definition for this function, nothing more is required.
In a nutshell, the compiler will only look for the definitions it needs, if it finds a matching template, it will generate the definitions. Otherwise it will mark the symbol as missing and it is your responsibility that the linker will have it available.

Is static member variable initialized in a template class if the static menber is not used?

Is static member variable initialized in a template class if the static member is not used? I use it to register the type.
template<class T>
class A
{
static bool d;
};
template<class T> bool A<T>::d = [](){regist<A<T>>(); return true;}();
int main()
{
A<int> a;
return 0;
}
I find a way to test it. It prints 1 other than 2. The regist() is not called abd the static member is not initialized. My testing is on VC110 compilter. And I also test it online
#include <iostream>
using namespace std;
int i = 1;
template<class T>
void regist()
{
++i;
}
template<class T>
class A
{
static bool d;
};
template<class T> bool A<T>::d = [](){regist<A<T>>(); return true;}();
int main()
{
A<int> a;
cout << i << endl;
return 0;
}
The relevant section of the C++ draft standard comes under 14 Templates which is 14.7.1 Implicit instantiation paragraph 2 which says(emphasis mine):
Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
We can also see paragraph 8 which says:
The implicit instantiation of a class template does not cause any static data members of that class to be implicitly instantiated.
However if you add an explicit instantiation to the second case as follows you will see 2 as the results:
template<> bool A<int>::d = [](){regist<A<int>>(); return true;}();
Yes it is initialized run this sample program, but only because it is forced to exist.
template <class T>
struct A
{
static int b;
};
template <class T> int A<T>::b = 10;
#include <iostream>
using namespace std;
int main() {
cout << A<int>::b << endl;
return 0;
}
I believe this quote from the standard may clarify any doubts
[Note: Once the static data member has been defined, it exists even if no objects of its class have been created. [ Example: in the example above, run_chain and running exist even if no objects of class process are created by the program. — end example ] — end note ]
Here is a relavent part of the standard that confirms your suspicisions.
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 se- mantics of the program. The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions or default arguments, of the class member func- tions, member classes, static data members and member templates; and it causes the implicit instantiation of the definitions of member anonymous unions. Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly in- stantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
The two parts I highlighted in bold I think clear up your issue. Clearly the reason for this behavior is that if no explicit specialization is given the compiler has no way to decide how many times the code should be executed (infinite possible types)

Full specialization of method template from class template

I know this subject should be pretty much dated by now, but I'm having a tough time with this specific case.
Straight to the point, this is what I want to do:
enum MyEnum
{
E_1,
E_2
};
template <MyEnum T>
class MyClass
{
// method to be fully specialized
template <typename U>
void myMethod(U value);
};
// full specialization of method template from class template
// (or is this in fact partial, since I'm leaving T alone?)
template <MyEnum T>
template <>
void MyClass<T>::myMethod<int>(int value)
{
std::cout << value << '\n';
}
Is this possible?
C++03 [$14.7.3/18] says
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.
So you need to specialize the enclosing class too.
Something like this would work.
template <>
template <>
void MyClass<E_1>::myMethod<int>(int value)
{
std::cout << value << '\n';
}
Since you leave T, while specializing only function template, then what you're trying to do would be called partial specialization, because T is still templated and you can use it in your function. But unfortunately, partial template specialization of function (whether be it member function or non-member function) is not allowed. So your code would give compilation error.
Either you fully specialize by specializing the class template as well, or you don't at all.

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.

C++ template "deferred instantiation"

What is meant with "deferred instantiation" in C++ templates?
Deferred instantiation is when the template is not instantiated until the corresponding entity is used for the first time. For example, you have a templated function:
template<int Size>
void YourFunction()
{
//does something
}
parameter Size can have any possible value that int can have. Do you automatically have the templated function instantiated for all possible values of Size? No, the template is only instantiated for the values that are actually used as the parameter when the function call first appears in the code:
YourFunction<100>(); //instantiated for 100
I have only heard people use the term "deferred instantiation" to refer to the situation where a class member definition is instantiated only if it is used
template<typename T>
struct A {
void f() {
T a; // invalid if T is void
}
};
A<void> a; // valid!
In this case, A<void> is implicitly instantiated because the compiler needs to know its size (formally, the class type needs to be complete, so an instantiation is triggered). But the instantiation of its member definitions are deferred until they are actually used. This does not only apply to member functions, but also to static data members and nested classes
struct Print {
Print() { std::cout << "hello!"; }
};
template<typename T>
struct A {
static Print print;
};
template<typename T>
Print A<T>::print;
Now even if you implicitly instantiate A<T> the message won't be printed until you explicitly refer to A<T>::print and use it. Explicit instantiation won't defer instantiation of member definitions - so the following will always print the message
template struct A<void>;
There is a trick to trigger instantiation of member definitions for implicit instantiations though: Refer to them in declaration parts of a class' member, like in the following changed class template
template<typename T, T&> struct useit { };
template<typename T>
struct A {
static Print print;
typedef useit<Print, print> useit_type;
};
Now if A<T> is implicitly instantiated the message is printed, because the typedef declaration refers to it.