我很困惑为什么这些函数中的一个会出现硬错误,而另一个不会:
#include <utility>
template <typename ...Args>
auto ffExists1()
-> decltype(ff(std::declval<Args>()...)); // Attempts to see
// whether you can call ff (which is not defined or declared)
// with arguments of type Args... This works fine.
template <typename ...Args>
auto ffExists2() -> decltype(&ff); // Gives me a hard error : ff not defined
这是为什么?另外,如何制作
ffExists2
工作?使用指向函数的指针可以让我确定 ff
的确切签名。而ffExists1
只知道我是否可以调用ff
参数类型为 Args...
.编辑:这是一个版本,其中
ffExists2
取决于模板,导致相同的结果:#include <utility>
template <typename ...Args>
auto ffExists() -> decltype(ff(std::declval<Args>()...)); //Fine
template <typename ... Args>
void SomeHelperFunc(auto (*) (Args...));
template <typename ...Args>
auto ffExists2() -> decltype(SomeHelperFunc<Args...>(&ff)); // Hard Error
最佳答案
在 ffExists2
, ff
不依赖于模板参数,因此查找它(即通过提供的名称查找函数)在 two-phase lookup 的第一阶段完成,即当编译器第一次看到模板时,而不是模板参数被替换到它时。
正因为如此,即使 ff
在此模板之后定义,这无关紧要,因为第一阶段 is already done by that point .
另一方面,在 ffExists1
,查找 ff
取决于模板参数(因为 ADL 是此查找的一部分,并且 ADL 需要知道参数的类型,即 Args...
),因此对其的查找被推迟到第二阶段,即到实例化点的模板,
at which time ADL examines function declarations that are visible from the template definition context as well as in the template instantiation context, while non-ADL lookup only examines function declarations that are visible from the template definition context (in other words, adding a new function declaration after template definition does not make it visible except via ADL).
— (c) cppreference
没有办法制作
&ff
依赖于模板参数,并且不可能对不依赖于模板参数的事物执行 SFINAE 检查。任何尝试都将受到以下因素的阻碍:
[temp.res.general]/6.1
The program is ill-formed, no diagnostic required, if:
— no valid specialization can be generated for a template ...
你会认为 C++20
requires
可以提供帮助,因为您可以在没有任何模板的情况下使用它,但是唉:
[expr.prim.req.general]/5
...
[Note 1: If a requires-expression contains invalid types or expressions in its requirements, and it does not appear within the declaration of a templated entity, then the program is ill-formed. — end note]
If the substitution of template arguments into a requirement would always result in a substitution failure, the program is ill-formed; no diagnostic required.
关于c++ - C++ 中的表达式 SFINAE 和硬错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66770807/