GCC 手工制作的 constexpr 查找 vs std::find

GCC hand made constexpr find vs std::find

我正在尝试使用 c++17 实现 constexpr 查找,以查找数组中匹配元素的索引 (from cppreference) very similar to 。下面是一个非常简单的实现,其中包含 int数组。

namespace mine{
    template<typename InputIter, typename T>
    constexpr inline InputIter find(InputIter first, InputIter last, const T& val)
    {
        for(; first!=last; ++first)
            if(*first == val) return first;

        return first;        
    }
}

int main()
{
    const std::array<int, 5> a{4, 10, 5, 889, 45};
    auto b = mine::find(a.begin(), a.end(), 5);
    auto c = std::distance(a.begin(), b);

    return c;
}

问题是 GCC 主干无法在编译时推断 mine::find!! (live code mine::find)。 然而,只需将开关更改为 -std=c++2a(因为 c++20 将 std::find 标记为 constexpr),std::find 会给我预期的结果 (live code std::find) .

编辑: 如何在不更改 main() 中的代码的情况下获得与 std::findmine::find 相同的优化级别相同的结果? (mind::find 当然可以更改,保持类似的界面) 是什么让 GCC 针对相同的优化级别优化 std::find 更好?

编辑 2: 在此处将 b 声明为 constexpr 会产生错误 (live code with error)

int main()
{
    const std::array<int, 5> a{4, 10, 5, 889, 45};
    constexpr auto b = mine::find(a.begin(), a.end(), 5);
    auto c = std::distance(a.begin(), b);

    return c;
}

注意:Clang trunk 似乎可以正确推断 mine::find。但这与 constexpr 恕我直言没什么关系,因为即使没有它,clang 也会推断出结果。

除非在 const 表达式中使用,否则不需要在编译时调用 constexpr 函数。然后你依赖编译器优化。

在 constexpr 中转换您的(调用)代码可确保编译时计算:

int main()
{
    static constexpr std::array<int, 5> a{4, 10, 5, 889, 45};
    constexpr auto b = mine::find(a.begin(), a.end(), 5);
    constexpr auto c = std::distance(a.begin(), b);

    return c; // return 2 directly
}

Demo