template <typename T>
int get_num(const T&)
{
return 42;
}
struct Foo
{
int i = get_num(*this);
};
int get_num(const Foo&)
{
return 23;
}
int main()
{
std::cout << Foo().i << std::endl; // MinGW64 - 42, MSVC - 23
return 0;
}
MSVC chooses non-template get_num "overload". It will successfully link even if the template is only forward-declared.
MinGW64 will choose the default template implementation. Will fail to link if there is no definition for the template.
Who is right and who is wrong? Whad does the standard say?
However this version yields the same results for both compilers... Why does it not go to infinite recursion?
template <typename T>
int get_num(const T& t)
{
std::cout << "Template version called" << std::endl;
return get_num(t);
}
struct Foo
{
int i = get_num(*this);
};
int get_num(const Foo&)
{
std::cout << "Non-Template version called" << std::endl;
return 23;
}
MSVC output:
Non-Template version called
23
MinGW64 Output:
Template version called
Non-Template version called
23
I think ADL is involved when using MSVC.
For the first sample, MinGW is correct and MSVC is incorrect: the get_num call can only consider the function template.
This is a question of overload resolution, so I'll start in clause [over]. get_num(*this) is a plain function call expression, so [over.call.func] applies:
In unqualified function calls, the name is not qualified by an -> or . operator and has the more general form of a primary-expression. The name is looked up in the context of the function call following the normal rules for name lookup in function calls. The function declarations found by that lookup constitute the set of candidate functions.
"Name lookup" is discussed in section [basic.lookup]. Paragraph 2:
A name "looked up in the context of an expression" is looked up as an unqualified name in the scope where the expression is found.
One complication here is that the get_num(*this) default member initializer expression doesn't get used by anything until the default constructor of Foo is implicitly defined by its odr-use in main. But the lookup is determined from the code location of the expression itself, no matter that it's used in the process of that implicit definition.
For the second code sample, MinGW is again correct: the apparently recursive call inside the template definition actually calls the non-template function.
This is a result of "two phase lookup" for dependent function calls, described in section [temp.dep.res]. Briefly, since the type of t depends on a template parameter, the name get_num in the expression get_num(t) is considered a dependent name. So for each instantiation of the function template, it gets two ways of finding candidates for overload resolution: the ordinary immediate way which finds the get_num function template, plus another lookup from the point of instantiation. The specialization get_num<Foo> has point of instantiation right after the main() definition, so overload resolution is able to find the non-template from the instantiation context, and the non-template wins overload resolution.
(Argument-dependent lookup is a related tangent issue to this second point. ADL applies to declarations from the instantiation context but not declarations from the definition context. But it's not directly a reason for the behaviors in either example program.)
None of this has changed significantly between C++14 and the latest draft, as far as I can see.
Related
After looking at the proposed resolution of #1664(proposed resolution 1664), I'm confused for the rules of a default argument of a function template, Cite the content here:
According to 8.1.5 [expr.prim.lambda] paragraph 3
The closure type is declared in the smallest block scope, class scope, or namespace scope that contains
the corresponding lambda-expression. [Note: This determines the set of namespaces and classes associated with the closure type (6.4.2 [basic.lookup.argdep]). The parameter types of a lambda-
declarator do not affect these associated namespaces and classes. —end note]
However, 17.8.1 [temp.inst] paragraph 13 says
If a function template f is called in a way that requires a default argument to be used, the dependent names are looked up, the semantics constraints are checked, and the instantiation of any template used in the default argument is done as if the default argument had been an initializer used in a function template specialization with the same scope, the same template parameters and the same access as that of the function template f used at that point.
A possibility, then, is that the closure type for lambda expression in a default argument for a template function (or, presumably, a member function of a class template) is to be considered as having been declared in some block scope in the body of the fictional function template specialization.
Consider the following example:
namespace J {
inline namespace K {
template <typename T> int zap(const T &t) { foo(t); return 0; }
template <typename T> void zip(int = zap([] { })) { }
}
template <typename T> void foo(const T &) { }
}
void bar() {
J::K::zip<long>();
/*Accroding to the above wording,the invoke just like:
=> J::K::zip<long>(zap([] { }));
*/
}
If zip were not a template, argument-dependent lookup successfully resolves the lookup for foo in all implementations tested; however, there is implementation variance in the handling of the example as written.
Proposed resolution (September 2013):
Change 17.8.1 [temp.inst] paragraph 13 as follows:
If a function template f is called in a way that requires a default argument to be used, the dependent names are looked up, the semantics constraints are checked, and the instantiation of any template used in the default argument is done as if the default argument had been an initializer used in a function template specialization with the same scope, the same template parameters and the same access as that of the function template f used at that point, except that the scope in which a closure type is declared (8.1.5 [expr.prim.lambda]) — and therefore its associated namespaces — remain as determined from the context of the definition for the default argument. This analysis is called default argument instantiation. The instantiated default argument is then used as the argument of f.
Note the emphasized part,if I do not misunderstand,It means if the emphasized part comment out,the foo could not be looked up by argument dependent look up because the argument [] { } which namespace is neither J nor K,assume the form within function bar like J::K::zip<long>(zap([] { }) /*default argument*/);,So accroding to [expr.prim.lambda] paragraph 3 the namespace of [] { } is at fuction bar and at that scope,there's no foo can be found,So the emphasized part is for this case that consider the namespace of [] { } within zap as the same as zap,it means the namespace of [] { } is K,Now the foo can be found in the parent namespace J by argument dependent lookup rules ,So far ,If i misundertand these rules,please correct me.the other point view is that the default argument is evaluated every time when the function called,even if the default is non-dependent.So continue consider the following code:
#include <iostream>
struct A {
};
template<typename T>
int func(T, float) { //#a
std::cout << "float" << std::endl;
return 0;
}
template<typename T>
void test(int = func(A{}, 0)) { //#1
}
template<typename T>
int func(T, int) { //#b
std::cout << "int" << std::endl;
return 0;
}
int main() {
test<A>(); //#2 transform to: test<A>(func(A{}, 0)); here,#b should be the best match
std::getchar();
}
Although the default argument func is non-dependent,However it should be determined every time when the function test is called and I test the code in some compliers.
All the version of MSVC report "int",gcc report "float",clang report "float",what's the hell?Accroding to the report of gcc or clang,It seems to the func is determined at #1and MSVC proved that the func is determined at #2. if MSVC is wrong ,that means the non-dependent default argument could be determined within #1 and it's unnecessary to determine every time when the function called,why the emphasized part need to add?(If I understand the emphasized part correctly,the purpose of it is that keep the namespace of closure type within default argument consistent whether the lambda-expression is at the point of function declaration or the point of call). If I misunderstand these rules,How to interpret them correctly?
UPDATE:
the version 9.1 or higher of gcc can not complie the code mentioned in #1664,it will report error (the complie result)
Questions:
1.Does the non-dependent default argument of function template or non-template function need to determined every time when the corresponding function called?
2.what does "the definition for the default argument" mean?Is this wording strictly?(In other word,my understanding is,what actullay the added rules want to express is that the namespace of closeure type is that of a function declartion where contain a default argument which contain the corresponding lambda-expression,Right?if my understanding about this is wrong,correct me)
Default arguments are evaluated every time they are called, but this is a runtime property: calls are counted not by source line but by actual control flow. Separately, a default argument for a templated function is considered to be a definition and is instantiated when needed, up to once per specialization of the function (with the usual proviso about multiple points of instantiation that must agree). CWG1664 was a very narrow issue based on how that instantiation was worded: by introducing a fictitious function template, it left open the possibility that the lambda’s declaration “physically” moved. The fix really does affect only ADL.
Your func example instead illustrates the usual name-lookup rules in templates: no matter how many times and whence test’s default argument is instantiated, func in it is not a dependent name and thus finds func(T,float) (every time). MSVC has famously never implemented this rule correctly (because, to be fair, their implementation predates the rule and they’ve only recently started the requisite (and nearly complete) rewrite of their template support).
Meanwhile, recent GCC is plainly buggy with the CWG1664 example: note that it complains about foo being used but not defined, contradicting both the plainly visible { } and its prior error message about not finding it.
This program works as expected:
#include <iostream>
template <typename T>
void output(T t) {
prt(t);
}
struct It {
It(int* p) : p(p) {}
int* p;
};
void prt(It it) {
std::cout << *(it.p) << std::endl;
}
int main() {
int val = 12;
It it(&val);
output(it);
return 0;
}
When you compile and execute this, it prints "12" as it should. Even though the function prt, required by the output template function, is defined after output, prt is visible at the point of instantiation, and therefore everything works.
The program below is very similar to the program above, but it fails to compile:
#include <iostream>
template <typename T>
void output(T t) {
prt(t);
}
void prt(int* p) {
std::cout << (*p) << std::endl;
}
int main() {
int val = 12;
output(&val);
return 0;
}
This code is trying to do the same thing as the previous example, but this fails in gcc 8.2 with the error message:
'prt' was not declared in this scope, and no declarations were found by
argument-dependent lookup at the point of instantiation [-fpermissive]
The only thing that changed is that the argument passed to output is a built-in type, rather than a user-defined type. But I didn't think that should matter for name resolution. So my question is: 1) why does the second example fail?; and 2) why does one example fail and the other succeeds?
The Standard rule that applies here is found in [temp.dep.candidate]:
For a function call where the postfix-expression is a dependent name, the candidate functions are found using the usual lookup rules ([basic.lookup.unqual], [basic.lookup.argdep]) except that:
For the part of the lookup using unqualified name lookup, only function declarations from the template definition context are found.
For the part of the lookup using associated namespaces ([basic.lookup.argdep]), only function declarations found in either the template definition context or the template instantiation context are found.
In both examples, unqualified name lookup finds no declarations of prt, since there were no such declarations before the point where the template was defined. So we move on to argument-dependent lookup, which looks only in the associated namespaces of the argument types.
Class It is a member of the global namespace, so the global namespace is the one associated namespace, and the one declaration is visible within that namespace in the template instantiation context.
A pointer type U* has the same associated namespaces as type U, and a fundamental type has no associated namespaces at all. So since the only argument type int* is a pointer to fundamental type, there are no associated namespaces, and argument-dependent lookup can't possibly find any declarations in the second program.
I can't exactly say why the rules were designed this way, but I would guess the intent is that a template should either use the specific declared functions it meant to use, or else use a function as an extensible customization point, but those user customizations need to be closely related to a user-defined type they will work with. Otherwise, it becomes possible to change the behavior of a template that really meant to use one specific function or function template declaration by providing a better overload for some particular case. Admittedly, this is more from the viewpoint of when there is at least one declaration in the template definition context, not when that lookup finds nothing at all, but then we get into cases where SFINAE was counting on not finding something, etc.
The below code is part of a cpp quiz that I was going through :
#include <iostream>
template<typename T>
void foo(T)
{
std::cout << "T" << std::endl;;
}
struct S
{
};
template<typename T>
void call_foo(T t)
{
foo(S());
foo(t);
}
void foo(S)
{
std::cout << "S" << std::endl;
}
int main()
{
call_foo(S());
}
I fail to understand why the output turns out to be TS. I expected it to be SS
Compiler : gcc version 4.8.5 20150623
§14.6¶9 states: "When looking for the declaration of a name used in a
template definition, the usual lookup rules (§3.4.1, §3.4.2) are used
for non-dependent names. The lookup of names dependent on the template
parameters is postponed until the actual template argument is known
(§14.6.2)."
The first call to foo is a non-dependent call, so it is looked up at the time of definition of the function template. In case of the second call, it is deferred until the template is instantiated because it depends on a template parameter.
template<typename T> void call_foo_function(T t)
{
foo(S()); // Independent, looks up foo now.
foo(t); // Dependent, looks up foo later.
}
When foo is being looked up at the time of definition of the function template, the only version of foo that exists is the templated foo(T). Specifically, foo(S) does not exist yet, and is not a candidate.
Interesting thing would be check what your code outputs in Visual Studio, I think in that case it would output the SS that you expected.
Source of the answer : CPPQuiz.
Unfortunately, I do not have the exact link of the answer anymore since I am not able to find it again.
You were expecting the two calls to be resolved identically, via argument dependent lookup. But in this case:
foo(S());
foo(t);
The first foo is not a dependent name. Recall that name lookup for functions in templates is done in two ways:
Regular unqualified name lookup for all the overloads at the point of the function template's definition.
For dependent names, argument dependent lookup is done at both the point of template definition and instantiation.
Since, again, the first call is not dependent, only regular unqualified name lookup is done. At that point, the only visible overload is the function template foo you defined previously. The second overload is not yet available, hence it's not called.
Consider the following code:
#include <iostream>
template<typename T>
void f(T t)
{
(void)t;
std::cout << "templated f(T)\n";
}
template<typename T>
void entry(T t)
{
f(t);
}
void f(double d)
{
(void)d;
std::cout << "normal f(double)\n";
}
int main()
{
double d = 0.0;
entry(d);
return 0;
}
Output:
templated f(T)
I find this surprising, because I thought that the plain function will be selected over any templated version. Why does this happen?
Another thing I noticed while playing around is that: if I put the normal function void f(double) before the templated void entry(T) function the code will call the normal function, basically outputting:
normal f(double)
Therefore my other question: why does the order matter in this particular example?
f is a dependent name, since it depends on t whose type is a template parameter. The name lookup rules for dependent names are given in [temp.dep.res]/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.
In other words, normally name lookup inside a template only finds names that have been declared before the template definition (which is not that surprising, since it's the same as for non-templates). The second bullet point allows names declared after the template definition to be found, but only when ADL occurs. This won't be the case when the argument is a fundamental type such as double.
The overload for f(double) is not visible to the compiler when the entry(T) template is parsed. Therefore, it won't participate in overload resolution when the entry(T) template is instantiated. This is just an obscure rule when it comes to resolving overloads in a template instantiation context. In order for an overload to be considered, it has to already have been visible in the translation unit before the template definition was parsed.
I'm wondering why the following code compiles.
#include <iostream>
template<class T>
void print(T t) {
std::cout << t;
}
namespace ns {
struct A {};
}
std::ostream& operator<<(std::ostream& out, ns::A) {
return out << "hi!";
}
int main() {
print(ns::A{});
}
I was under impression that at the instantiation point unqualified dependent names are looked-up via ADL only - which should not consider the global namespace. Am I wrong?
This is an interesting case. The workings of name lookup as you describe them is summarized here:
[temp.dep.candidate] (emphasis mine)
1 For a function call where the postfix-expression is a dependent
name, the candidate functions are found using the usual lookup rules
([basic.lookup.unqual], [basic.lookup.argdep]) except that:
For the part of the lookup using unqualified name lookup, only function declarations from the template definition context are found.
For the part of the lookup using associated namespaces ([basic.lookup.argdep]), only function declarations found in either
the template definition context or the template instantiation context
are found.
If 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 bit I highlighted is the crux of the matter. The description for "ADL only" is for function calls of the from foo(bar)! It does not mention calls that result from an overloaded operator. We know that calling overloaded operators is equivalent to calling a function, but the paragraph speaks of expressions in a specific form, that of a function call only.
If one was to change your function template into
template<class T>
void print(T t) {
return operator<< (std::cout, t);
}
where now a function is called via postfix-expression notation, then wo and behold: GCC emits an equivalent error to Clang. It implements the above paragraph reliably, just not when it comes to overloaded operator calls.
So is it a bug? I would say it is. The intent is surely that overloaded operators be found like named functions (even when called from their respective expression form). So GCC needs to be fixed. But the standard could use a minor clarification of the wording too.