Formally (quote from std would be ideal), from which point a definition of this class starts:
template<typename T>
class X
{
};
from which point a definition of this class starts
From the point compiler starts parsing things related to the class. In your example, the letter "t" of the word template is the start, hence the point of definition!
By the way, there're two related things. Read this:
Point of definition vs Point of instantiation
The point of definition of a template
is located immediately before its
definition. In this example, the point
of definition of the function template
g(T) is located immediately before the
keyword template. Because the function
call f(123) does not depend on a
template argument, the compiler will
consider names declared before the
definition of function template g(T).
Therefore, the call f(123) will call
f(double). Although f(int) is a better
match, it is not in scope at the point
of definition of g(T).
The point of instantiation of a
template is located immediately before
the declaration that encloses its use.
In this example, the point of
instantiation of the call to
g(234) is located immediately
before i(). Because the function call
h(a) depends on a template argument,
the compiler will consider names
declared before the instantiation of
function template g(T). Therefore, the
call h(a) will call h(double). It will
not consider h(int), because this
function was not in scope at the point
of instantiation of g(234).
Quoted from Name binding and dependent names (C++ only)
Although, it talks about function template, the same is true of class template as well.
It is a class template and it's definition starts from the word template.
From Standard docs., 14.1,
A template defines a family of classes or functions, or an alias for a family of types.
template-declaration:
exportopt template < template-parameter-list > declaration
And,
A template-declaration is a declaration. A template-declaration is also a definition if its declaration defines a function,
a class, or a static data member.
So, formally the template declaration is the definition for the templated class which starts with the word template in your example.
Related
According to [temp.spec]/5:
For a given template and a given set of template-arguments,
...
an explicit specialization shall be defined at most once in a program (according to [basic.def.odr]), and
...
the definition of an explicit (full) specialization of a class template cannot be placed in a header (otherwise there is one definition in each translation unit containing this header, thus there will be more than one definition in the whole program).
In addition, as another evidence, the entities listed in [basic.def.odr]/12 (blockquoted below) do not contain a full specialization of a class template. Instead, "template specialization for which some template parameters are not specified" is contained.
There can be more than one definition of a class type, enumeration type, inline function with external linkage ([dcl.inline]), inline variable with external linkage ([dcl.inline]), class template, non-static function template, concept ([temp.concept]), static data member of a class template, member function of a class template, or template specialization for which some template parameters are not specified ([temp.spec], [temp.class.spec]) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements.
However, if I place the definition in a source file and leave its declaration in a header, for example,
// "a.h"
template <typename T>
struct S {};
template <>
struct S<int>; // declaration
// "a.cpp"
#include "a.h"
template <>
struct S<int> {}; // definition
// "main.cpp"
#include "a.h"
int main()
{
S<int> s;
}
then an error occurs (tested by gcc) because S<int> is an incomplete type.
In conclusion, where should I place the definition of an explicit specialization of a class template?
I am going to try to summarize here what I've learned through the discussion in my other answer, in the hopes of leaving a good answer to this question, rather than having the answer be buried in the comments.
The standard says
an explicit specialization shall be defined at most once in a program (according to ODR)
ODR is the One Definition Rule. You can only define each class once within a program, with an exception designed to allow a class definition to be available in each translation unit: you can define a class in different translation units as long as these different definitions are identical, character for character. The quote of the OP is part of the ODR description, follow the OP's link to see the full description.
So IMO the standard's text above means that an explicit specialization can be defined only once, but according to the ODR, and thus with the same exceptions: you can define it in a header file so it is available in multiple translation units.
Note that it is not possible to instantiate a class without its full definition (the compiler needs to know at least how many bytes to allocate for it). The same is true for a templated class, or a specialization of such a class. So it must be possible for the definition to be present in each translation unit that uses it.
This is a definition (the specialization will be instantiated), not a declaration, it probably ought to go in a specific source file (*.cpp):
template <> struct S<int>;
Note: it doesn't "hurt" to have this in every translation unit... other than the time it takes to instantiate by the compiler, and the bloat for the object files (*.o or *.obj).
This is a declaration (the specialization will not be instantiated), and is okay to put in a header file (*.h):
extern template <> struct S<int>;
The declaration requires C++11 or later.
The N4296::14.7.1/1 [temp.inst] provides the following example:
template<class T, class U>
struct Outer {
template<class X, class Y> struct Inner;
template<class Y> struct Inner<T, Y>; // #1a
template<class Y> struct Inner<T, Y> { }; // #1b; OK: valid redeclaration of #1a
template<class Y> struct Inner<U, Y> { }; // #2
};
Outer<int, int> outer; // error at #2
and the following explanation is given:
Outer<int, int>::Inner<int, Y> is redeclared at #1b. (It is not
defined but noted as being associated with a definition in
Outer<T, U>.) #2 is also a redeclaration of #1a. It is noted as
associated with a definition, so it is an invalid redeclaration of the same
partial specialization.
I was confused by the fact that #1b is treated as a declaration, but not a definition. We explcitily provided the function body there, and why isn't it still a definition? In fact, couldn't you explain that exlnation.
This is explained in the text immediately preceding the example!
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 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. However, for the purpose of determining whether an instantiated redeclaration of a member is valid according to 9.2, a declaration that corresponds to a definition in the template is considered to be a
definition.
There is a difference between the definition of the function that results from instantiating the templates, and a definition of the function templates themselves.
A name is introduced into its scope with its first declaration and is then associated with an entity such as an object, function or class. In certain scopes, such as namespace scope or class scope, a name may be declared multiple times. A declaration of name may also include a definition of the named entity. After a definition is seen, it is said that the declaration in question is associated with a definition. No more than one definition is allowed for a named entity.
When a class template is instantiated implicitly, the definitions of its nested functions, classes and static object members are not instantiated immediately. They are only instantiated as soon as they are needed. However, there's a special rule to catch potential definition conflicts.
In this example, in a class template with two parameters, T and U, an inner class template with two parameters, X and Y, is declared. Two partial specializations are defined for the inner class, one for the case when X coincides with T and another for the case when X coincides with U. The first partial specialization is first declared at #1a and then redeclared and associated with a definition at #1b. The second partial specialization is declared and associated with a definition at #2.
So far so good.
But what if T and U are the same type, for example, int? In such a case, for any given Y, declarations in #1a, #1b, and #2 all declare the same name, Outer<int, int>::Inner<int, Y>. Two of these declarations are associated with definitions and that causes conflict. The example in N4296 you quote is to demonstrate that the conflict must be diagnosed even though there are no references that require the instantiation of Outer<int, int>::Inner<int, Y>.
Outer<int, char> is fine because in this case T and U do not coincide and therefore the #2 gives definition to Outer<int, char>::Inner<char, Y> which is different from Outer<int, char>::Inner<int, Y> defined in #1b.
I have a function void f<int N>(). f is only called with template parameters 1 and 2, e.g. f<1>() and f<2>() and I have efficiently specialized f for those two parameters. f will never be called with any other parameter, but I have defined f with general N anyway, just for "clarity". Question: Will the compiler still instantiate this unused definition of f<N>()? If so, I feel like this will create code bloat, as I have dozens of functions of this sort located in very performance-critical areas of the program.
(Instead, I'm considering commenting the f<N>() definition and replacing it with an empty definition, i.e. void f<N>(){}.)
A template is not instantiated unless it is used.
From Standards :
§ 14.7.1/10
An implementation shall not implicitly instantiate a function
template, a member template, a non-virtual member function, a member
class, or a static data member of a class template that does not
require instantiation. It is unspecified whether or not an
implementation implicitly instantiates a virtual member function of a
class template if the virtual member function would not otherwise be
instantiated. The use of a template specialization in a default
argument shall not cause the template to be implicitly instantiated
except that a class template may be instantiated where its complete
type is needed to determine the correctness of the default argument.
The use of a default argument in a function call causes
specializations in the default argument to be implicitly instantiated.
I am playing a bit with static polymorphism, I'm calling a function which internally calls the "right" specialized function depending on the type of the initial argument (basically I'm doing tagging). Here is the code:
#include <iostream>
using namespace std;
// tags
struct tag1{};
struct tag2{};
// the compliant types, all should typedef tag_type
struct my_type1
{
using tag_type = tag1;
};
struct my_type2
{
using tag_type = tag2;
};
// static dispatch via tagging
template <typename T>
void f(T)
{
cout << "In void f<typename T>(T)" << endl;
// why can I call f_helper without forward definition?!?
f_helper(typename T::tag_type{});
}
int main()
{
my_type1 type1;
my_type2 type2;
// how does f below knows about f_helper ?!?!
// even after instantiation f_helper shouldn't be visible!
f(type1);
f(type2);
}
// helper functions
void f_helper(tag1)
{
cout << "f called with my_type1" << endl;
}
void f_helper(tag2)
{
cout << "f called with my_type2" << endl;
}
So, f(T) is called with a parameter my_type1 or my_type2 that internally must typedef tag_type with the appropriate tag tag1/tag2. Depending on this internal tag_type, the "right" wrapper is then called, and this decision is made of course at compile time. Now I really don't understand why this code IS working? Why don't we need to forward-declare f_helper? I first had the wrappers defined before main (and after f), and I though ok, this makes sense, you don't need to forward declare because the compiler instantiate the template only when f(type1); is called (in main()), before it doesn't know the type T, so at the time of instantiation the compiler knows f_wrapper.
But as you see, even if I declare the wrappers AFTER main(), the code still works. Why is this happening? I guess the question is a bit strange, asking why a code works :)
EDIT
The code continues to compile even in gcc5 and gcc HEAD 6.0.0.
f_helper(typename T::tag_type{}) is a type-dependent expression because T::tag_type is a dependent type. This means that f_helper doesn't need to be visible until f<T> is instantiated due to two phase lookup.
EDIT: I'm pretty sure that this is actually undefined behaviour. If we look at 14.6.4.2 [temp.dep.candidate] we see this passage:
For a function call that depends on a template parameter, the
candidate functions are found using the usual lookup rules (3.4.1,
3.4.2, 3.4.3) except that:
— For the part of the lookup using unqualified name lookup (3.4.1) or qualified name lookup (3.4.3), only
function declarations from the template definition context are found.
— For the part of the lookup using associated namespaces (3.4.2), only
function declarations found in either the template definition context
or the template instantiation context are found.
If the function name
is an unqualified-id and the call would be ill-formed or would find a
better match had the lookup within the associated namespaces
considered all the function declarations with external linkage
introduced in those namespaces in all translation units, not just
considering those declarations found in the template definition and
template instantiation contexts, then the program has undefined
behavior.
The last paragraph to me indicates this is undefined behaviour. The function call that depends on a template parameter here is f_helper(typename T::tag_type{}). f_helper isn't visible when f is instantiated, but it would be if we performed name lookup after all translation units have been compiled.
I agree, the code is ill-formed. I'm surprised neither g++ nor clang++ has even a warning about this.
14.6.2/1:
In an expression of the form:
postfix-expression ( expression-list [opt] )
where the postfix-expression is an id-expression, the id-expression denotes a dependent name if any of the expressions in the expression-list is a type-dependent expression (14.6.2.2) or if the unqualified-id of the id-expression is a template-id in which any of the template arguments depends on a template parameter. ... Such names are unbound and are looked up at the point of the template instantiation (14.6.4.1) in both the context of the template definition and the context of the point of instantiation.
[f_helper is a postfix-expression and id-expression, and typename T::tag_type{} is type-dependent, so f_helper is a dependent name.]
14.6.4/1:
In resolving dependent names, names from the following sources are considered:
Declarations that are visible at the point of definition of the template.
Declarations from namespaces associated with the types of the function arguments both from the instantiation context (14.6.4.1) and from the definition context.
14.6.4.1/6:
The instantiation context of an expression that depends on the template arguments is the set of declarations with external linkage declared prior to the point of instantiation of the template specialization in the same translation unit.
14.6.4.2/1:
For a function call that depends on a template parameter, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2, 3.4.3) except that:
For the part of the lookup using unqualified name lookup (3.4.1) or qualified name lookup (3.4.3), only function declarations from the template definition context are found.
For the part of the lookup using associated namespaces (3.4.2), only function declarations found in either the template definition context or the template instantiation context are found.
The call to f_helper(typename T::tag_type{}); is dependent on the template parameter T, so the name f_helper need not be visible until the point of instantiation of f<T> (due to two phase name lookup).
I believe the code works because implementations are allowed to delay the point of instantiation of function templates until the end of the translation unit, at which time the definitions for f_helper are available.
N3936 §14.6.4.1/8 [temp.point]
A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one
definition rule (3.2), the program is ill-formed, no diagnostic required.
I came across an interesting point that I wasn't able to explain or find an explanation for. Consider the following template definition (compiled with mingw g++ 4.6.2):
template <typename T, typename S>
class Foo
{
public:
void f(){}
void g(){}
};
Should we want to, we can fully specialize any single member function:
template <>
void Foo<char,int>::f() {}
But partial specialization fails with an "invalid use of incomplete type 'class Foo<...>'" error:
template <typename T, typename S>
void Foo<T,S*>::f()
{
}
template <typename T>
void Foo<T,int>::f()
{
}
And I can't figure out why. Is it a conscious design decision made to avoid some problem I can't foresee? Is it an oversight?
The notion of partial specialization only exists for class templates (described by §14.5.5) and member templates (i.e. members of a template class that are themselves template functions, described by §14.5.5.3/2). It does not exist for ordinary members of class templates, nor does it exist for function templates – simply because it is not described by the Standard.
Now, you might argue that by giving the definition of a partial specialization of a member function, such as
template <typename T>
void Foo<T,int>::f()
{ }
you implicitly define a partial specialization of the class template: Foo<T,int>. That, however, is explicitly ruled out by the Standard:
(§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).
(§14.5.5.3/1) [...] 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. [...]
The latter implies that it is impossible to implicitly define a partial specialization by simply giving the definition of one of its members: The very existence of that member would not follow from the definition of the primary template, hence defining it is equivalent to defining a member function that wasn't declared, and that isn't allowed (even with non-template classes).
On the other hand, the notion of explicit specialization (or full specialization, as you call it) exists for member functions of class templates. It is explicitly described by the Standard:
(§14.7.3/1) An explicit specialization of any of the following:
[...]
— member function of a class template
[...]
can be declared by a declaration introduced by template<>; [...]
§14.7.3/14 describes the details:
(§14.7.3/14) A member or a member template of a class template may be explicitly specialized for a given implicit instantiation of the class template, even if the member or member template is defined in the class template definition. [...]
Hence, for explicit specializations of members, the instantiation of the rest of the class template works implicitly – it is derived from the primary template definition, or any partial specializations if defined.
I tried to find a succinct quote from the standard, but I don't think there is one. The fact is, there is no such thing as a partial specialization of a template function (or, for that matter, of a template alias). Only class templates can have partial specializations.
Let's forget about templates for a second. In C++, there is a big difference between class names and function names. There can only be one definition of a class within a given scope. (You can have various declarations, but they all refer to the One True Class.) So the name really identifies the class.
A function name, on the other hand, is a kind of group identity. You can define any number of functions within a scope with exactly the same name. When you use a function name to call a function, the compiler has to figure out which function you really meant by looking at the various possibilities and matching the signature of each of them with the supplied arguments. There's no relationship between the various functions which share a name; they're completely separate entities.
So, no big deal. You knew all this, right? But now let's go back to templates.
The name of a templated class is still unique. Although you can define partial specializations, you have to explicitly specialize the same templated class. This mechanism looks superficially like the function-name resolution algorithm referred to above, but there are significant differences -- one of them is that, unlike function prototypes, you cannot have two class templates in the same scope with different kinds of template parameters.
Templated functions, on the other hand, have no need to define unique names. Templating does not replace the normal function overload mechanism. So when the compiler is trying to figure out what a function name means, it has to consider all templated and non-templated declarations for that function name, resolve the templated ones to a set of template parameter assignments (if possible) and then once it has a list of possible function objects, select the best one with normal overload resolution.
That's quite a different algorithm from the templated class template parameter resolution. Instead of just matching a list of provided template arguments with a list of declared template parameters, which is how it resolves class templates, it has to take each templated function which might possibly match (has at least the right number of parameters, for example); deduce template parameters by unifying the supplied arguments with the template; and then add the resolve specialization to the overload set for a further round of overload resolution.
I suppose it would have been possible to have added partial specialization resolution into that process as well, but the interactions between partial specialization and function overloading strike me as likely to lead to pseudo-magical behaviour. In the event, it wasn't necessary and so there is no such mechanism. (You can fully specialize a function template. Full specialization means that there are no template arguments to deduce, so it's not a problem.)
So that's the scoop: you can't partially specialize a templated function, but there is nothing stopping you from providing any number of function templates with the same name. All of them will be considered in overload resolution, and the best one will win, as usual.
Usually, that's actually sufficient for your overloading needs. You should think about templated functions just the same way you think about normal functions: come up with a way to select the one you want based on the supplied arguments. If you feel you really need to supply template parameters in a function call, rather than having them be deduced, just make the function a (possibly static) member of a templated class, and supply the template arguments to the class.
Hope that helps...
I think that the difference is that when you do the first (valid) explicit specialization of f:
template <>
void Foo<char,int>::f() {}
You are doing an implicit instantiation of Foo<char,int>. But when you try the partial specialization with:
template <typename T>
void Foo<T,int>::f()
{
}
The compiler would need to instantiate implicitly Foo<T,int> before doing the specialization, but it cannot do that because of the T. And it fails.
You can check that is the case with the following code:
template <typename T, typename S>
class Foo
{
public:
void f(){}
void g(){}
};
template <>
void Foo<char,int>::f() //line 11
{}
template <>
class Foo<char,int> //line 15
{};
With g++ it gives the errors:
test.cpp:15:7: error: specialization of ‘Foo<char, int>’ after instantiation
test.cpp:15:7: error: redefinition of ‘class Foo<char, int>’
test.cpp:2:7: error: previous definition of ‘class Foo<char, int>’
With clang++ is a bit clearer:
test.cpp:15:7: error: explicit specialization of 'Foo<char, int>' after instantiation
class Foo<char,int>
^~~~~~~~~~~~~
test.cpp:11:6: note: implicit instantiation first required here
void Foo<char,int>::f()
^