SFINAE 在使用异常时仍然产生错误

SFINAE still produces error while using exception

我正在学习 C++ 中的 SFINAE。所以在阅读之后,我正在尝试不同的例子来更好地理解这个概念。下面我给出了 2 个片段,其中 1 个我能理解,但第二个我在声明中使用 noexcept 我无法理解。

例1:我能理解。

#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;
}

以上程序的输出(如预期的那样)是:

ordinary timer called

我可以理解,由于SFINAE,推导会导致失败,所以会调用普通的timer

示例 2:为什么我们在这个示例中会出错。

#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;
}

第二个示例导致错误,指出 func 未声明。我的问题是,为什么像这里的示例1一样,由于推导失败也没有选择普通的timer

我预计这里也应该调用普通的timer,但事实并非如此。谁能解释一下背后的原因。

问题异常规范不参与模板参数推导(TAD).这在下面更详细地解释。 Source: C++ Templates: The Complete Guide Page No. 290

案例一

这里我们考虑示例1。在这种情况下,由于没有func函数模板声明中的错误timer triggers模板参数推导失败又名 SFINAE,通过选择普通函数 timer 允许调用 timer(5); 成功,您将获得预期的输出。

案例二

这里我们考虑示例 2。在这种情况下,因为异常规范不参与 TAD,重载解析 选择函数模板版本,因此当异常规范实例化时稍后,程序变为 ill-formed 并且您会收到上述错误。

换句话说,异常规范仅在需要时实例化,就像默认调用参数