我有一个类,其成员函数以“谓词”类型为模板。直到最近,MSVC 编译器接受了以下代码,但现在它说它无法推断谓词的模板参数。
我怀疑编译器回归,但我尝试了 clang(在编译器资源管理器上),它也表示无法推断谓词类型。
为什么不呢?
请注意,只需包裹
std::isalpha
即可解决问题。我不明白为什么。字符分类器有什么特别之处吗?
#include <cctype>
#include <iostream>
int WrappedIsAlpha(int ch) { return std::isalpha(ch); }
int MyIsAlpha(int ch) {
return ('A' <= ch && ch <= 'Z') ||
('a' <= ch && ch <= 'z');
}
class Foo {
public:
explicit Foo(char ch) : m_ch(ch) {}
template <typename Predicate>
bool Match(Predicate P) const {
return P(m_ch) != 0;
}
private:
char m_ch;
};
int main() {
Foo foo('x');
// The compiler is unable to infer the type for the Predicate
// template parameter. (MSVC used to be OK with it.)
std::cout << foo.Match(std::isalpha) << std::endl;
// Wrapping the function solves the problem. Why/how?
// Don't these have the same signature as `std::isalpha`?
std::cout << foo.Match(WrappedIsAlpha) << std::endl;
std::cout << foo.Match(MyIsAlpha) << std::endl;
return 0;
}
[上面的代码使用 x64 MSVC v19.37 进行编译(在编译器资源管理器上),但对于我的本地版本 19.38.33133,模板参数推断失败。 clang 17.0.1(在编译器资源管理器上)与较新版本的 MSVC 一致。]
[前几条评论指出了问题。由于没有人发布答案,我将在这里捕获它作为社区答案。]
该标准限制程序获取 std 命名空间中大多数函数的地址。 @heapunderrun 提供了 cppreference.com 的该限制的摘要的链接,我发现这特别有帮助。
许多标准库函数不一定实现为实际函数。它们可能是内在函数或其他形式的编译器魔法。这就是为什么对大多数人的地址进行限制。
我知道 C 标准库的一些实现将字符分类函数实现为宏。由于宏不能位于命名空间中,因此我假设 C++ 标准库将它们实现为函数。这不是一个可靠的假设。