为什么谓词模板参数推理在某些情况下有效,但在其他情况下无效?

问题描述 投票:0回答:1

我有一个类,其成员函数以“谓词”类型为模板。直到最近,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 一致。]

c++ templates type-inference predicate
1个回答
0
投票

[前几条评论指出了问题。由于没有人发布答案,我将在这里捕获它作为社区答案。]

该标准限制程序获取 std 命名空间中大多数函数的地址。 @heapunderrun 提供了 cppreference.com 的该限制的摘要的链接,我发现这特别有帮助。

许多标准库函数不一定实现为实际函数。它们可能是内在函数或其他形式的编译器魔法。这就是为什么对大多数人的地址进行限制。

我知道 C 标准库的一些实现将字符分类函数实现为宏。由于宏不能位于命名空间中,因此我假设 C++ 标准库将它们实现为函数。这不是一个可靠的假设。

© www.soinside.com 2019 - 2024. All rights reserved.