I have a class with a member function templated on a "predicate" type. Until recently, the MSVC compiler accepted the following code, but now it says that it cannot infer the template argument for the predicate.
I suspected a compiler regression, but I tried clang (on Compiler Explorer), and it, too, says the predicate type cannot be inferred.
Why not?
Note that just wrapping std::isalpha solves the problem. I don't understand why. Is there something special about the character classifiers?
#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;
}
[The above code compiles with x64 MSVC v19.37 (on Compiler Explorer), but the template argument inferencing fails for my local version 19.38.33133. clang 17.0.1 (on Compiler Explorer) agrees with the newer version of MSVC.]
[The first few comments identified the problem. Since nobody posted an answer, I'll capture it here as a community answer.]
The standard restricts programs from taking the address of most functions in the std namespace. @heapunderrun provided a link to cppreference.com's summary of that restriction, which I found especially helpful.
Many standard library functions are not necessarily implemented as actual functions. They may be intrinsics or other forms of compiler magic. That's why there's a restriction on taking the address of most of them.
I know some implementations of the C standard library implemented the character classification functions as macros. Since macros cannot be in a namespace, I had assumed that the C++ standard library implemented them as functions. That was not a reliable assumption.