【问题标题】:C++ code that compiles in gcc 9.3 but not in gcc 10.2在 gcc 9.3 中编译但在 gcc 10.2 中不编译的 C++ 代码
【发布时间】:2021-05-24 03:05:59
【问题描述】:

以下代码在 gcc 9.3 中编译,但在 gcc 10.2 中不编译:

constexpr std::array<int, 2> opt = {1,2};          

template <typename T>
constexpr auto f(const T& arr) 
{
    std::array<int, arr.size()> res{};
    return res;
}

int main()
{
    auto res = f(opt);
 
}

代码在https://godbolt.org/z/8hb6M8

gcc10.2给出的错误是arr.size() is not a constant expression

哪个编译器是正确的? 9.3 还是 10.2?

如果 10.2 是正确的,我如何定义编译时数组并将其大小(和数组)作为参数传递?

【问题讨论】:

    标签: c++ gcc constexpr c++20 stdarray


    【解决方案1】:

    不知道哪个是正确的,但适合

    如何定义编译时数组并将其大小(和数组)作为参数传递?

    你可以把函数改成

    template <typename T, std::size_t N>
    constexpr auto f(const std::array<T, N>& arr) 
    {
        std::array<int, N> res{};
        return res;
    }
    

    现在尺寸被提升到模板参数中。

    【讨论】:

    • 是的,但我不想返回相同大小的数组。我想返回另一个尺寸:std::array&lt;int, size_of_subset_of(arr)&gt; res{}。对不起,也许我没有正确表达我的意图。但我必须考虑如何去做。我问这个问题是因为我不知道为什么两个编译器的行为不同,这意味着我不太了解 constexpr 的工作原理。感谢您的帮助。
    • @Antonio 你的代码使用了arr.size(),所以这就是我认为你想要的。要使size_of_subset_of(arr) 工作,您需要使size_of_subset_of 成为我在此处使用的函数,以便您可以从模板参数中获取数组大小并使用它来计算子集大小。
    【解决方案2】:

    另一种适用于两种编译器且不需要更改模板声明的替代方法:

    std::array<int, std::tuple_size_v<T>> res{};
    

    【讨论】:

    • std::extent_v 不适用于 std::array(仅限原始数组)
    • @Artyer 哦,该死的。我只是试图编译它,它确实如此。它只返回 0。编辑为改用 std::tuple_size_v
    【解决方案3】:

    从C++20开始,常量表达式的定义发生了变化,你可以在this找到几处变化。

    更简短的答案是更改您的函数签名:

    template <typename T>
    constexpr auto f(const T& arr);
    

    进入:

    template <typename T>
    constexpr auto f(const T arr);
    

    然后works

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-06
      • 2015-05-08
      • 1970-01-01
      • 2020-06-03
      • 2014-09-09
      • 2020-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多