Maestro
Maestro

Reputation: 2552

Why in a template we can use a dependent name without being already declared if not instantiated?

I have written this code to understand template name lookup:

//void bar(int);

template <typename T>
void foo(T x)
{
    bar(x);
}

void bar(int x)
{
    std::cout << "bar(int)\n";
}

template <int>
void foo(int i)
{
    bar(i);
}



int main()
{

    foo<int>(4);


    std::cout << "\ndone!\n";
}

I've commented out the declaration of function bar(int) intentionally. This function bar(int) is used as a dependent name in the template function foo. So it is bound upon instantiation.

But when I compile the code I get this error:

‘bar’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]|. And if I un-comment the declaration of bar(int) it works fine?!

So what is the idea behind allowing calling print(u) in do_it which was not already declared and will fail upon instantiation?

Upvotes: 0

Views: 141

Answers (2)

cigien
cigien

Reputation: 60218

In your program, this definition:

template <int>     // not a specialization, just a different
void foo(int i)    // template with a non-type template parameter
{
    bar(i);
}

does not actually define a specialization of the foo primary template. So when you make this call:

Foo<int>(4);

you end up calling the primary template. Lookup for the name bar doesn't find that name, and you get an error.

If instead, you actually write a specialization of foo for int like this:

template <>           // specialization of primary
void foo<int>(int i)  // template foo with int
{
    bar(i);
}

then the call foo<int>(4); is fine, because it calls the specialization, and lookup for bar at that point does find that name.


Now going back to your program (without the specialization), what happens if foo is never instantiated, because there's no call, for example? Well, the program is still wrong, but the compiler may not tell you about it. This is the behavior that you are describing with print and do_it, and this is formally known as ill-formed, no diagnostic required.

Upvotes: 3

Timothy Brackett
Timothy Brackett

Reputation: 181

Pay attention to the line numbers in that error output.

You’re instantiating the first template. The second template is not a specification of the first but a function template that requires an int template parameter that it doesn’t use.

Upvotes: 1

Related Questions