【发布时间】:2023-03-25 01:46:01
【问题描述】:
来自 cppreference:
当需要函数模板特化的 noexcept 规范但尚未实例化时,将查找从属名称并实例化表达式中使用的任何模板,就像声明特化一样。
有人可以提供一些例子吗?
可以在此处查找哪些名称(是否必然涉及 ADL,或者是否只是必须自行查找的普通依赖类型名称)?
我很难理解上面的意思。
【问题讨论】:
标签: c++ templates c++14 noexcept name-lookup
来自 cppreference:
当需要函数模板特化的 noexcept 规范但尚未实例化时,将查找从属名称并实例化表达式中使用的任何模板,就像声明特化一样。
有人可以提供一些例子吗?
可以在此处查找哪些名称(是否必然涉及 ADL,或者是否只是必须自行查找的普通依赖类型名称)?
我很难理解上面的意思。
【问题讨论】:
标签: c++ templates c++14 noexcept name-lookup
它基本上意味着当noexcept-specification 需要(这是一个特定的术语)时,它被实例化。当它被实例化时,它的实例化方式与函数模板声明的实例化方式相同——包括为此必须发生的一切。
cppreference 示例有:
template<class T> T f() noexcept(sizeof(T) < 4);
decltype(f<void>()) *p; // error
即使我们没有评估 f,它的 noexcept-specification 也是需要(因为 f 是通过重载决议选择的,并且会是 odr - 如果已评估则使用)。所以在那一点上它被实例化了。但该实例化是一个错误,因为 sizeof(void) 格式不正确。
另一方面,这个稍作修改的版本是可以的:
template<class T> T f(int);
template<class T> T f() noexcept(sizeof(T) < 4);
decltype(f<void>(1)) *p; // ok
我们从不实例化 f() 的 noexcept 规范,因为它不是必需的。
名称查找没有什么特别之处。这只是正常的模板规则适用,所以:
struct N {
struct X { };
void h(X);
}
void h(int) noexcept;
template<class T> void g(T t) noexcept(noexcept(h(t))
当需要g 的noexcept-specification 时,那就是实例化h(t)——它可能会也可能不会像往常一样执行 ADL。 noexcept(g(0)) 将是 true,但 noexcept(g(N::X{})) 将是 false。
此外,任何相关模板仅在需要时才被实例化。所以如果我们有:
template<class T> struct X;
template<class T> T f() noexcept(X<T>::value);
template<class T> T f(int);
X<T> 只会在需要 noexcept-specification 时被实例化,而不是之前。所以decltype(f<int>(0)) 不会尝试实例化X<int>,但decltype(f<int>()) 将是一个硬错误,因为X<int> 是一个不完整的类型,所以X<int>::value 是格式错误的。
【讨论】: