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 instantiatingfunc2<int>
at its usage infunc1
?
It had no reason. The primary template provided the int func2<int>()
prototype it needed to continue.