Search code examples
c++templatesexceptionc++14sfinae

SFINAE still produces error while using exception


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.


Solution

  • 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

    Case 1

    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.

    Case 2

    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.

    Pic 1

    Pic 2