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() {}
};
Related
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.openstd.org/jtc1/sc22/wg21/docs/cwg_toc.html#727
8 http://www.openstd.org/jtc1/sc22/wg21/docs/cwg_toc.html#1755
9 http://accu.org/cgibin/wg21/message?wg=core&msg=24366(24033, 24290, 24309, 24368)
10 http://accu.org/cgibin/wg21/message?wg=core&msg=24731(24731, 24732, 24736, 24738)
11 http://accu.org/cgibin/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.
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. [...]
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.
template <typename T>
struct A
{
template <typename U>
struct B;
template <>
struct B<int> {static const int tag = 1;}; // Works fine in VS2010
};
How can I specialize B the same way, but outside of A. I tried this with no success :
template <typename T> template <>
struct A<T>::B<int> {static const int tag = 1;};
I get:
error C3212: 'A<T>::B<int>' : an explicit specialization of a template member must be a member of an explicit specialization
It does not make sense since I can do exactly that by defining it inside the class
VS2010 problem? Wrong syntax?
Thanks
PS: This one (which should be wrong anyway, crashes VS2010):
template <> template <typename T>
struct A<T>::B<int> {static const int tag = 1;};
To quote the C++ spec, §14.17.3.18:
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 unspecialzed, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well. [...]
(my emphasis)
This suggests that you can't specialize a template class nested inside another template class unless the outer template class is specialized as well. So it looks like VS2010 has this behavior wrong and g++ has it right.
It just doesn't work that way.:-(
You cannot specialize a function inside the class declaration, even though msvc accepts this with its default settings.
You also cannot specialize a member function without also specializing the enclosing class. Most compilers avred on this (as does the language standard).
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.