I am learning about SFINAE in C++. So after reading about it, i am trying out different examples to better understand the concept. Below i have given 2 snippets out of which 1 i can understand but the second one where i have used noexcept
in the declaration i can't understand.
Example 1: I am able to understand this.
#include <iostream>
template<typename T>
decltype(func(T())) timer(T a)
{
std::cout<<"template timer called"<<std::endl;
return func(T());
}
void timer(...)
{
std::cout<<"ordinary timer called"<<std::endl;
}
int main()
{
timer(5);
return 0;
}
The output of the above program(as expected) is:
ordinary timer called
I can understand that due to SFINAE the deduction will result in failure and so the ordinary timer
will be called.
Example 2: Why do we get error in this example.
#include <iostream>
template<typename T>
void timer(T a) noexcept(func(T()))
{
std::cout<<"template timer called"<<std::endl;
}
void timer(...)
{
std::cout<<"ordinary timer called"<<std::endl;
}
int main()
{
timer(5);
return 0;
}
This second example results in an error saying that func
was not declared. My question is why just like example 1 here also due to deduction failure the ordinary timer
isn't selected?
I expected that here also ordinary timer
should have been called but it isn't the case. Can someone explain the reason behind it.
The problem is that exception specification do not participate in template argument deduction(TAD). This is explained in more detail below. Source: C++ Templates: The Complete Guide Page No. 290
Here we consider example 1. In this case, since there is no func
the error in the declaration of the function template timer
triggers template argument deduction failure aka SFINAE which allows the call timer(5);
to succeed by selecting the ordinary function timer
and you get the expected output.
Here we consider example 2. In this case, because exception specification do not participate in TAD, overload resolution selects the function template version and so when the exception specification is instantiated at later time, the program becomes ill-formed and you get the mentioned error.
In other words, exception specifications are only instantiated when needed just like default call arguments.