I am trying to understand how template argument deduction works in C++. And so writing out different examples. One such example which doesn't work and i can't understand why is given below:
#include<iostream>
template<int var, typename T>
void func (T x)
{
std::cout<<x<<std::endl;
}
template<typename T>
void SomeFunc(T a)
{
a(6);
}
int main()
{
func<5, int>(10);//this work as expected
func<5>(20);//this works as well using template argument deduction
SomeFunc(func<5,int>) ;//this works as well
//the next two calls doesn't work
SomeFunc(func<5>);//this doesn't work. Why doesn't template argument deduction works here
SomeFunc(func<5>(20));//this doesn't work either.
return 0;
}
In the above example, the statement SomeFunc(func<5>);
doesn't work. My thinking is that when the compiler tries to instantiates SomeFunc<>
it needs its template type parameter. But we have passed func<5>
as the function call argument without actually calling(specifying the call argument to func itself) func
so there is no way to deduce the second parameter and so it doesn't work. My first question is that is my analysis of why this call fails correct? If not then why doesn't it work.
Next in the statement SomeFunc(func<5>(20));
i have specified the function call argument 20
to func
which was not specified in the previous call. But still this statement doesn't work. Why is this so?
While reading about template argument deduction i also came across the following statement:
Deduction only works for immediate calls.
But i could not understand what the above quoted statement means. It may have to do something with the fact that complete type or incomplete type used as template argument but i am not sure.
SomeFunc(func<5,int>);
You pass a pointer to the function func<5,int>
and T
becomes void(*)(int)
which is fine. It also works inside SomeFunc
when you use the function pointer a
to call the function it is pointing at.
SomeFunc(func<5>);
Deduction is not possible. The compiler is not able to look forward to see that inside SomeFunc
you will call a(6)
so therefore it must instantiate func<5,int>
and make a
point at it.
SomeFunc(func<5>(20));
Here you actually call func<5,int>
(with the argument 20
) and pass the return value from that call into SomeFunc
. There is no return value from func<5,int>
since it's void
and void a;
is not valid. If it had been valid, the next problem would have been that you try to call a
in SomeFunc
. The argument to SomeFunc
must be a callable of some sort or else a(6);
will fail.