gpt4 book ai didi

c++ - std::abs 可以在 constexpr 函数中使用,但前提是它是模板化的。为什么?

转载 作者:行者123 更新时间:2023-12-02 09:58:12 25 4
gpt4 key购买 nike

据说 std::abs不是 constexpr在标准中(甚至在 C++20 中)。但在实践中我发现我可以将其编译为 constexpr在函数模板化的非常特殊的条件下。请参阅这个完全有效的示例:

template<class T>
constexpr T f(const T input) {
return std::abs(input);
}

int main() {
int i = -1;
int a = f(i);
return 0;
}
编码:
  • 使用 GCC 编译得很好,无论有没有模板。
  • 它在 Clang 中不起作用。
  • 在 Visual Studio 中,它使用模板行进行编译,但在没有模板的情况下编译失败。
  • 最佳答案

    对于常规函数 编译器可能会根据函数参数的类型知道内部代码是否可以在编译时进行评估。这就是调用 std::abs 时出现错误的原因。在 MSVC 和 clang 中。 gcc 的行为基于其决定实现 std::absconstexpr顺便说一句 a questionable decision .
    对于模板函数 编译器无法知道是否可以在编译时评估内部代码,因为它可能基于模板参数的实际类型,调用不同的函数重载。虽然大多数编译器会决定不检查 std::abs 是否所有可能的重载|不能是 constexpr ,从而让代码通过编译,理论上编译器可以检查(在可以检查的非常特定的情况下,例如这个)并且由于不允许用户扩展 std通过添加新版本的 abs (允许扩展到 std 的列表已被规范关闭)可以看到该函数永远不可能是 constexpr从而产生编译错误。然而,在更一般的情况下,如果所有可能的情况都不能产生 constexpr,编译器就无法检查模板函数。函数,因为它只看到内部调用的可用重载,每次调用模板函数时,当在别处调用模板时,内部调用可能还有其他可用的重载。

    请注意,制作 constexpr函数模板,只是为了它可以被编译,这不是一个好方法。实际决定是否函数是constexpr (即可以在编译时调用)将基于实际调用,如果在所有情况下该函数都不能是 constexpr你试图以某种方式欺骗编译器,但最终主要是欺骗你自己......

    顺便说一句,在我检查 clang 10.1 和主干版本时,我没有收到模板版本的编译错误,此代码 compiles both with gcc and clang :

    template<typename T>
    constexpr T myabs(T t) {
    return std::abs(t);
    }

    int main() {
    int i = myabs(3);
    }
    虽然这用 gcc 编译(它实现了 std::absconstexpr )并且失败了:
    int main() {
    constexpr int i = myabs(3);
    }
    即使在 constexpr 中进行内部调用,gcc 和 clang 似乎也不会产生错误。模板函数不依赖于模板参数 and can never be a constant expression :
    int myabs() {
    return 42;
    }

    template<class T>
    constexpr int f() {
    // this is never a contexpr
    // yet gcc and clang are ok with it
    return myabs();
    }
    同样,这是允许的,因为不符合要求不需要诊断 constexpr模板函数:
    [dcl.constexpr] 9.2.5/7 - The constexpr and consteval specifiers :

    [...] If no specialization of the template would satisfy the requirements for a constexpr function when considered as a non-template function, the template is ill-formed, no diagnostic required.

    关于c++ - std::abs 可以在 constexpr 函数中使用,但前提是它是模板化的。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64220243/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com