I can't understand why the standard first defines template instantiation for templates as follows N3797::14.7/4 [temp.spec]:
The act of instantiating a function, a class, a member of a class
template or a member template is referred to as template
instantiation.
But further everywhere it uses the instatiation of the specialization, like the following N3797::14.7/4 [temp.spec]:
An instantiated template specialization can be either implicitly
instantiated (14.7.1) for a given argument list or be explicitly
instantiated (14.7.2).
I don't understand that. A template itself is a different concept than the template specilization, which could be an explicit specialization or a partial specialization. For instance N3797::14.5.5/1 [temp.class.spec]:
The primary template shall be declared before any specializations of
that template.
My question is about why the Standard first declare the instatiation concept for templates, but further it applies that concept for template specializations?
Moreover N3797::14.7/4 [temp.spec] defines the specialization concept as follows:
A specialization is a class, function, or class member that is either
instantiated or explicitly specialized (14.7.3).
So, the partial specialization is not a specialization, is it? I'm totally confused by those concepts. Couldn't you clarify it a bit?
This is a similar question here.
And now,I try to answer this question again.
A template is a type of infinite, so we can not instantiate a template, we can only be instantiated template specialization.
Implicitly instantiated, the current compilation unit requires the use of the template code, the compiler automatically instantiated template specialization.
Explicitly instantiated, we manually enter the code causes the compiler to instantiate a template specialization.
explicit specialization, given all the template parameters, and gives a non-generic code. Once the template type match, then instantiate this specialization.
Partial specialization, some parameters are given template and gives a non-generic code. Once the template type match, then instantiate this specialization.
Related
While going through the various rules on list-initialization, I found this in dcl.init.list#3.6:
Otherwise, if T is a specialization of std::initializer_list<E>, the object is constructed as described below.
On the other hand, in the synopsis of std::initializer_list, in support.initlist, I found the following statement:
If an explicit specialization or partial specialization of initializer_list is declared, the program is ill-formed.
These appear to be contradictory statements, so what am I misunderstanding?
"A template specialization" has two distinct meanings:
"Explicit (full) specialization" or "partial specialization" - a language construct that changes the meaning of a template for some combination of template parameters.
Something that was generated from a template by substituting template arguments into it.
In other words, if you specify template arguments for a template, the resulting type/function/variable/... is a specialization of that template. E.g. std::vector<int> is a specialization of std::vector.
Looks like the first passage you quote uses (2).
So "if T is a specialization of std::initializer_list<E>" roughly means "if there exists such E that std::is_same_v<T, std::initializer_list<E>>", or "if T is a std::initializer_list<E>".
There is no contradiction.
If an explicit specialization or partial specialization of initializer_list is declared, the program is ill-formed.
Means you cannot declare a specialization. The compiler itself is allowed to stamp out specializations of std::initializer_list
The thing that might be causing you issue is that the concrete type you get out of a template is called a specialization. This is what the first paragraph is talking about. The second paragraph is talking about actually defining/declaring a specialization for std::initializer_list
I tried to do something today that I was surprised to realize didn't work. I have a template that takes a type and a value as parameters. I want to specialize on the type parameter, but leave the value parameter open. Like so
template <class T = void, bool Enabled = false>
struct seFoo {};
template <bool Enabled>
struct seFoo<int, Enabled> {};
// Doesn't work :(
seFoo<false> foo;
However, this leads to a compile error for too few template arguments. It appears the instantiation has to match the signature of the unspecialized template before the compiler will even look at the partial specialization.
Is there a way to get this to work?
If this approach fundamentally isn't possibly, I'm interested in alternative approaches.
Apparently I'm not the only one surprised by this. This article makes the same mistake towards the end.
No, you can't really do this.
Note that a class template partial specialization is not something you can use directly in any way. Its only function is that when you to attempt to use the primary template as normal, if the partial specialization is a match for your template arguments and is the best match among any other explicit / partial specializations, then the partial specialization is used instead of the primary template to generate the definition of that particular class type.
In some cases there are things you can do with default template arguments, defining your own meanings for template arguments, or other such tricks. But there's no way to have one template that can take either a type or a value as its first template argument, and you can't have two class templates or alias templates with the same name in the same scope.
According to [temp.inst]:
Unless a class template specialization has been explicitly instantiated or explicitly specialized, 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.
So if I get it right, it is possible to define a template class and use it without odr-use it. It then will not be instantiated.
My question: what is the more short and/or idiomatic way to define a non instantiable template class?
(I shouln'd ask two questions in one thread, but when does "the completeness of the class type [would] affect the semantics of the program"?)
The C++ standard prohibits friend declarations of partial specializations. (§14.5.3/8):
Friend declarations shall not declare partial specializations. [Example:
template<class T> class A { };
class X {
template <class T> friend class A<T*>; //error
};
--end example]
Other questions, e.g. this one,
have received answers that invoke this prohibition, but I would like to know the
rationale. I don't see it and can't find it with my favourite search engine. I
can find however that it goes right back to the C++98 standard, so presumably
the rationale is quite basic and clear. Can someone explain it to me?
I don't have a reference but I suspect that this is because it would result in the partial specialization being declared in the scope of the friend-declaring class rather than the scope of the template in question, and rather than creating a bunch of rules to force the friend declaration to result in the specialization being in the correct scope, they simply prohibit it.
Here is some undirect explanation:
http://www.cprogramming.com/tutorial/template_specialization.html
A final implementation detail comes up with partial specializations:
how does the compiler pick which specialization to use if there are a
combination of completely generic types, some partial specializations,
and maybe even some full specializations? The general rule of thumb is
that the compiler will pick the most specific template
specialization--the most specific template specialization is the one
whose template arguments would be accepted by the other template
declarations, but which would not accept all possible arguments that
other templates with the same name would accept.
I infer that maybe it is not permitted to prevent any ambiguity in the determination of specialization type.
Can I make generic function declarations at the start of my header file?
I can do template<class t> t func(t); then specialize it, but
Template Specialization VS Function Overloading
says not to do that.
First, you can surely declare a template function and then define it, and/or define specializations. But...
Function specializations must be full specializations, that is, you cannot partially specialize a template function. Now, while you can actually specialize the function template, providing overload may have advantages (and disadvantages), but in most cases it will be a better option.
You might want to read this: http://www.gotw.ca/publications/mill17.htm