This fails to compile with clang++, can anybody explain why ? (this compiles fine with g++)
struct X
{
template <typename T> X() {}
};
template X::X<int>();
int main() { return 1; }
instantiate.cc:7:13: error: qualified reference to 'X' is a constructor name rather than a type in this context
template X::X<int>();
^
instantiate.cc:7:14: error: expected unqualified-id
template X::X<int>();
^
2 errors generated.
Constructors don't have names. As much is said in [class.ctor]/1. They are special members that get defined by using the name of the class. But they themselves are nameless. While C++ allows us to reference c'tors in certain contexts by using the class name, those are limited. In general, we cannot name a c'tor.
And that is where the issue lies. To explicitly specify template arguments we must use the name of the templated entity. Constructors don't have names, and so we cannot specify their arguments explicitly.
This is the subject of a note in [temp.arg.explicit] that summarizes the intent of the normative text.
7 [ Note: Because the explicit template argument list follows the
function template name, and because conversion member function
templates and constructor member function templates are called without
using a function name, there is no way to provide an explicit template
argument list for these function templates. — end note ]
We can still instantiate or specialize constructors, but only if the template arguments don't have to be explicitly specified (if they are deducible, or come from a default template argument). E.g
struct X
{
template <typename T> X(T) {}
};
template X::X(int); // This will work
So Clang is not wrong to reject your code. And it's possible GCC is offering an extension. But ultimately, the standard doesn't offer a way to provide template arguments explicitly to constructor templates.
And upon further digging, there's CWG581, further confirming Clang's behavior is the intended one. It also seems to have made its way into the latest standard revision with some changes to the normative text.
I think Clang is correct. Even Gcc allows it, the templated constructor can't be used at all. The template parameter can't be deduced and we can't specify template argument explicitly for constructor template.
[temp.arg.explicit]/2
Template arguments shall not be specified when referring to a specialization of a constructor template ([class.ctor], [class.qual]).
[temp.arg.explicit]/8
[ Note: Because the explicit template argument list follows the function template name, and because constructor templates ([class.ctor]) are named without using a function name ([class.qual]), there is no way to provide an explicit template argument list for these function templates. — end note ]
Related
template<typename T, typename U = T>
struct Test{};
template<typename T>
void func(Test<T>){ //#1
}
int main(){
func(Test<int>{}); //#2
}
It seems to no rule in the standard that mentioned what situation the default argument is required for template-parameter.
In dcl.fct.default#1
If an initializer-clause is specified in a parameter-declaration this initializer-clause is used as a default argument. Default arguments will be used in calls where trailing arguments are missing.
In this section, the rule explicitly describe when to supply default arguments for a function call. However I haven't found a quote in the standard similar with the above sentence that describes when to supply default arguments as template arguments.
Such as Test<T> at #1. Maybe at #1, the specialization would be Test<T,T>, It's just inference. However, there's no formally terminology explicitly describe this in the standard.
The only quote that implies the default arguments as template arguments is in the following rule:
temp#arg-8
When a simple-template-id does not name a function, a default template-argument is implicitly instantiated when the value of that default argument is needed. [ Example:
template<typename T, typename U = int> struct S { };
S<bool>* p; // the type of p is S<bool, int>*
The default argument for U is instantiated to form the type S<bool, int>*. — end example ]
Consider the code at #1, Does the default argument need at #1? If it is(It seems to It need at that point because If I don't specify a default argument for template parameter U, then at the point #1 will occur an error. see godbolt outcome), According to the above quote, the default template-argument need to be implicitly instantiated, However at this point, T is a template-parameter and the definition of such function template instantiate nothing(It's just a function template definition at this point). So, How does the quote interpret this?
There is also this paragraph inside [temp.names]:
A template-id is valid if
there is an argument for each non-deducible non-pack parameter that does not have a default template-argument,
So one could consider that a default-argument is needed means a default-argument is needed in order to make the template-id valid and that when there lacks a template argument, the argument is the default argument value. But I have not found anything explicit in the standard for class templates. For function template this is more explicit. Probably nobody pointed out this hole in the standard because this is a common pattern: default is used in place of what is not user provided. Maybe it will not be changed because the definition of default in the english dictionary is already given:
IT. the way that something will happen or appear automatically, especially on a computer, if you do not make any different choices
-- cambrige online dictionary
According to the above quote, the default template-argument need to be implicitly instantiated, However at this point, T is a template-parameter and the definition of such function template instantiate nothing(It's just a function template definition at this point). So, How does the quote interpret this?
The key is the difference between need of instantiation and when referenced. In the example from [temp.arg]/8, the default template argument for U is instantiated because it is needed for the instantiation of S<bool>, which unambiguously resolves to S<bool, int>. In the OP's own example, instantiation of the instantiation-dependent default template argument for U will only follow after overload resolution resolves void func(Test<T>) as the best viable overload and thus instantiates it. Just inspecting candidate overloads as part of overload resolution, however, will not lead to instantiation of any of the candidates nor any of the function template candidates parameters that are, themselves, templates. It will, however, be referencing said template parameters as part of the overload resolution process (discarding non-viable candidates).
From [temp.deduct]/1 [emphasis mine]:
When a function template specialization is referenced, all of the template arguments shall have values. The values can be explicitly specified or, in some cases, be deduced from the use or obtained from default template-arguments. [...]
For the OP's particular example, the former (instantiation) only occurs after overload resolution has finished and a best viable overload has been instantiated (which in turn instantiates the class template function argument). The latter (a function/class template specialization being referenced to), however, applies also during overload resolution, even when discarding candidates that are either not viable or not the best viable match, candidates that will never lead to instantiations.
From [temp.deduct]/2 [emphasis mine]:
When an explicit template argument list is specified, the template arguments must be compatible with the template parameter list and must result in a valid function type as described below; otherwise type deduction fails. Specifically, the following steps are performed when evaluating an explicitly specified template argument list with respect to a given function template:
(2.1) The specified template arguments must match the template parameters in kind (i.e., type, non-type, template). There must not be more arguments than there are parameters unless [...]
and from [temp.deduct]/6 [emphasis mine]:
At certain points in the template argument deduction process it is necessary to take a function type that makes use of template parameters and replace those template parameters with the corresponding template arguments. This is done at the beginning of template argument deduction when any explicitly specified template arguments are substituted into the function type, and again at the end of template argument deduction when any template arguments that were deduced or obtained from default arguments are substituted.
it is clear that as part of the "end of template argument deduction", any template arguments that have not been explicitly specified will be either deduced or obtained from default arguments and substituted into the candidate function before discarding or ranking it as a viable overload. This applies without any relation to instantiation, and only in the context of a given specialization (that may not yet or ever be instantiated) being referenced, as part of overload resolution.
Finally, from [temp.deduct.type]/3 [emphasis mine]:
A given type P can be composed from a number of other types, templates, and non-type values:
[...]
(3.3) A type that is a specialization of a class template (e.g., A<int>) includes the types, templates, and non-type values referenced by the template argument list of the specialization.
we note that as part of function template argument deduction for a function template parameter that is a specialization of a class template, the function template parameter type (used for deduction against an argument) includes the types referenced by the template argument list of the template parameter, meaning the particular class template specialization (function template argument) is referenced, so that, as per [temp.deduct]/1, it will go through template argument deduction and default-argument inspection for any of its template arguments that are not explicitly specified.
I wrote the following code that hiding of member function templates.
#include <iostream>
struct A
{
template<int> void func()
{
std::cout<<"Function tamplate of A"<<std::endl;
}
};
struct B : A
{
template<char> void func()
{
std::cout<<"Function tamplate of B"<<std::endl;
}
using A::func;
};
int main()
{
B().func<0>();
}
This program working in in Clang compiler. Live demo Clang
But, GCC compiler give an ambiguity error.Live demo GCC
source_file.cpp: In function ‘int main()’:
source_file.cpp:22:17: error: call of overloaded ‘func()’ is ambiguous
B().func<0>();
So, Which compiler is correct?
Regarding the example in the OP: as pointed out to me by W.F., what matters here is that those are member function templates. You added a using declaration, which specifies ([namespace.udecl]/15):
When a using-declaration brings names from a base class into a derived
class scope, member functions and member function templates in the
derived class override and/or hide member functions and member
function templates with the same name, parameter-type-list, cv-qualification, and ref-qualifier (if any) in a base
class (rather than conflicting).
Note how template parameters aren't accounted. And it is Clang that treated the code correctly by hiding the int version.
On the other hand if one examines the example tobi303 suggested under your post, GCC is kinda in the right. This simply isn't specified to be resolved somehow.
For one, there's [temp.fct.spec]/3:
Trailing template arguments that can be deduced or
obtained from default template-arguments may be omitted from the list
of explicit template-arguments. [...] In contexts where deduction is
done and fails, or in contexts where deduction is not done, if a
template argument list is specified and it, along with any default
template arguments, identifies a single function template
specialization, then the template-id is an lvalue for the function
template specialization.
The text in bold indicates that your program is well-formed only if the template argument we give nominates a single specialization. And ostensibly, it doesn't, since according to [temp.arg.nontype]/1:
A template-argument for a non-type, non-template template-parameter
shall be one of:
for a non-type template-parameter of integral or enumeration type, a converted constant expression of the type of the
template-parameter;
And 0 fits both overloads as a converted constant expression. On account of there not being any ICS ranking for template arguments, this is ambiguous.
I'm aware that the compiler will not instantiation unused template functions as long as they are not virtual in a class.
In a simple case, if I have two overloaded template functions both of which take the same template arguments, it seems the compiler instantiates both overloads. I guess this is required so that the compiler can perform overload resolution? Are overloads exempt from the lazy-instantiation rule for function templates? I wasn't able to find the relevant text in the standard. Here is an example:
template<typename T>
void foo(T) {zzz}
template<typename T>
void foo(T*) {}
int main()
{
int* blah;
foo(blah);
}
I would expect no compiler error if the first overload was not instantiated, however I get the error.
Live Sample
It seems as though you're expecting only one of those overloads to be instantiated because only one of them will be called, but the compiler clearly has to instantiate both of them in order to determine whether either of them can be called and, if so, which one to use.
The more formal answer is that both templates are candidates because your T can always be pointerised, so both are "used" in that sense:
[C++14: 14.7.1/3]: Unless a function template specialization has been explicitly instantiated or explicitly specialized, the function template specialization is implicitly instantiated when the specialization is referenced in a context that requires a function definition to exist. Unless a call is to a function template explicit specialization or to a member function of an explicitly specialized class template, a default argument for a function template or a member function of a class template is implicitly instantiated when the function is called in a context that requires the value of the default argument.
[C++14: 14.7.1/10]: If a function template or a member function template specialization is used in a way that involves overload resolution, a declaration of the specialization is implicitly instantiated (14.8.3).
So, basically:
I guess this is required so that the compiler can perform overload resolution?
Correct.
Your question, however, already stems from a misconception that your first function template can be ignored: it can't be. zzz does not depend on any template parameters so SFINAE is not involved; even if SFINAE were involved, it could not help you with your invalid syntax. So, no matter what you do, that code is ill-formed:
template<typename T>
void nil() {zzz}
// g++ -c -std=c++11 -O2 -Wall -pedantic -pthread main.cpp
// main.cpp: In function 'void nil()':
// main.cpp:2:13: error: 'zzz' was not declared in this scope
// void nil() {zzz}
// ^
(live demo)
That being said, a diagnostic is not required in this case; in particular, Microsoft Visual Studio has historically silently accepted such code:
[C++14: 14.6/8]: Knowing which names are type names allows the syntax of every template to be checked. No diagnostic shall be issued for a template for which a valid specialization can be generated. If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required. If every valid specialization of a variadic template requires an empty template parameter pack, the template is ill-formed, no diagnostic required. If a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is done, and if the completeness of that type affects whether or not the program is well-formed or affects the semantics of the program, the program is ill-formed; no diagnostic is required. [..]
The same wording may also be found in C++11 and C++03, so this has always been the case. Your misconception is therefore understandable.
Incidentally, your observation regarding virtual functions is also not completely accurate:
[C++14: 14.7.1/11]: An implementation shall not implicitly instantiate a function template, a variable 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.
This is not an answer from the inner question, but it is related about the assumption of the question: "I would expect no compiler error if the first overload was not instantiated, however I get the error."
Sure? so, why this code generate a compiler error?
template<typename T>
void nil(T) {zzz}
template<typename T>
void foo(T*) {}
int main()
{
int* blah;
foo(blah);
}
because nil is not instantiated
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()
^
I came up with this after answering this question
I had a simple function template (C++11):
template<class elem_t, class list_t>
bool in_list(const elem_t& elem, const list_t& list) {
for (const auto& i : list) {
if (elem == i) {
return true;
}
}
return false;
}
But GCC emitted warnings because it doesn't seem to like deducing a template parameter as a std::initializer_list. So, without thinking, I made a specialization:
template<class elem_t>
bool in_list(const elem_t& elem, std::initializer_list<elem_t> list) {
for (const auto& i : list) {
if (elem == i) {
return true;
}
}
return false;
}
This worked. No more warnings. But when I looked again and thought about it, I remembered that C++ does not support partial template specialization on function templates. But that is what this appears to be. My only guess is that this is allowed because std::initializer_list is still dependent upon the template parameter, so it is, in essence, a different template. But I'm not sure if this is how it is supposed to be (isn't there a gotw about templates not overloading?).
Is it standard behavior to accept this? And why?
And as a bonus question, why does GCC not like deducing a template parameter as a std::initializer_list? It seems quite silly to expect me to copy and paste the code and just replace the parameter with a std::initializer_list.
The warning message:
test.cpp: In function ‘int main()’:
test.cpp:33:43: warning: deducing ‘const list_t’ as ‘const std::initializer_list<int>’ [enabled by default]
test.cpp:6:6: warning: in call to ‘bool in_list(const elem_t&, const list_t&) [with elem_t = int, list_t = std::initializer_list<int>]’ [enabled by default]
test.cpp:33:43: warning: (you can disable this with -fno-deduce-init-list) [enabled by default]
When called by in_list(3, {1, 2, 3, 4, 5});
EDIT: Apparently deducing a template parameter as an initializer_list is an extension according to the working draft for my version of GCC (cite). So new question: Is this still an extension as of the final c++11 standard? If so, this would mean that it would be necessary for me to add the second function for standards-compliant code. Thanks for all your help!
EDIT2: The compiler dialect flag appears to be removed for GCC 4.7, so it seems like the issue was resolved, but I don't know how it was resolved.
Using what #Ben Voigt said in the comments on the other answer, I have gathered some relevant standard quotes:
§14.5.6.2
A function template can be overloaded with other function templates
and with normal (non-template) functions. A normal function is not
related to a function template (i.e., it is never considered to be a
specialization), even if it has the same name and type as a
potentially generated function template specialization.
So that rules out function template specialisation as what you're doing, because even if two function template overloads could potentially generate the same function, it's not specialisation. So it's overloading.
Such specializations are distinct functions and do not violate the one definition rule (3.2).
So they're distinct functions and that's why it's not erroring.
§14.5.6.2.1
If a function template is overloaded, the use of a function template
specialization* might be ambiguous because template argument deduction
(14.8.2) may associate the function template specialization with more
than one function template declaration.
This is priming is for what we both already saw, which is that in_list(a, b) where b is an initializer_list appears to match both function templates.
(*Note that "function template specialization" here doesn't mean specialising a function template, it means a function template that has been instantiated with a type. So with template<typename T> f();, f<int>() is a function template specialisation.)
So we use what is called partial ordering of overloaded function templates to resolve this:
Partial ordering of overloaded function template declarations is
used in the following contexts to select the function template to which a function
template specialization
refers:
— during overload resolution for a call to a function template specialization (13.3.3);
— when the address of a function template specialization is taken;
— when a placement operator delete that is a function template specialization is selected to match a placement operator new (3.7.4.2, 5.3.4);
— when a friend function declaration (14.5.4), an explicit instantiation (14.7.2) or an explicit specialization (14.7.3) refers to a function template specialization.
Ok, so that's when partial ordering is for. This is what it does:
Partial ordering selects which of two function templates is more
specialized than the other by transforming each template in turn (see
next paragraph) and performing template argument deduction using the
function type. The deduction process determines whether one of the
templates is more specialized than the other. If so, the more
specialized template is the one chosen by the partial ordering
process.
And then you get into the long and laborious process of determining which template is more specialised, which you can read about if you want, but it's really complicated and I probably don't understand it all (and plus, I don't have enough time to write about it :)).
That's not partial specilization. What you are doing is overloading function.