Home > database >  Specialization after instantiation error is not showing un-defined error
Specialization after instantiation error is not showing un-defined error

Time:12-07

I have experienced some issues with templates and their behaviour recently in our codebase which is pretty big. It's rather fascinating how simple-to-understand level-1 templates, become more complex as code size increases.

To reproduce one such instance:

#include <iostream>

template <typename T>
int func2();

// uncommenting this make this code work
// template <>
// int func2<int>();

int func1()
{
    int val = func2<int>();
    return val;
}

template <>
int func2<int>()
{
    return 20;
}

int main()
{
    std::cout << func1() << std::endl;
    return 0;
}

I get the compile error: specialization after instantiation at line 17. https://godbolt.org/z/sbqoK5Yvd

I think it would be really helpful if the compiler mentioned exactly where and what it had instantiated the template, in a large code-base it gets confusing.

Afaik, the compiler instantiates the definition of a class/function/variable when it encounters it's first usage. But looking at my code, I never defined func2<T>. Why didn't it report func2<int>() definition not found, when instantiating func2<int> at its usage in func1? I never defined func2<T>. Why does it go ahead, and checks ok-wow we found a specialization for an instantiated template, reports one error but forgets about un-defined error?

A better version of my doubt would be, how does the instantiation looks like, for this example? My naive brain would think - it would be a template instantiation for the declaration like:

// compiler 
template <>
int func2<int>();

//and thus, using func2<int> should report un-defined 

Is my understanding incorrect?

A good resource on templates at intermediate level, will be really helpful and definitely a bonus for me.

CodePudding user response:

When the compiler reaches

int val = func2<int>();

it'll "instantiate" the only function template prototype it's seen so far:

template <typename T>
int func2();

You later provide a specialization, but it's too late. It has used the primary template to get a prototype for int func2<int>() already.

Why didn't it report func2<int>() definition not found, when instantiating func2<int> at its usage in func1?

It had no reason. The primary template provided the int func2<int>() prototype it needed to continue.

  • Related