Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected output on calling template function

Tags:

c++

gcc

templates

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

like image 599
BlahGuy Avatar asked Mar 07 '23 12:03

BlahGuy


2 Answers

§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.

like image 65
Vishaal Shankar Avatar answered Mar 16 '23 19:03

Vishaal Shankar


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.

like image 41
StoryTeller - Unslander Monica Avatar answered Mar 16 '23 19:03

StoryTeller - Unslander Monica