You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

g++14编译C++20 generator/ranges代码时出现构造错误求助

解决g14编译C20生成器与ranges管道的错误

问题描述

使用g14编译一段利用C20 generator 特性生成迭代序列,并通过ranges管道将vector元素转换后合并为multiset的代码时,出现两个编译错误:

  • 找不到匹配的std::construct_at函数调用
  • new初始化表达式列表被当作复合表达式(提示添加-fpermissive选项)

原代码

#include <vector>
#include <ranges>
#include <algorithm>
#include <functional>
#include <generator>
#include <set>
using namespace std;

struct Edge
{
    uint64_t u,v;
};

int main()
{
    const vector<Edge> predecessor={};

    auto walk = [&](int64_t u)->generator<int64_t>{
        while (u != 0)
        {
            co_yield u;
            u = predecessor[u].u;
        }
    };
    
    const vector<int64_t> v={0,1,2};
    const auto ms = v |
        views::transform(walk) |
        views::join |
        ranges::to<multiset>() ;
    
    return 0;
}

编译错误信息

在实例化'static constexpr void std::allocator_traits<std::allocator<_Up>>::construct(allocator_type&, _Up*, _Args&& ...)'时,/opt/wandbox/gcc-head/include/c++/14.0.1/bits/alloc_traits.h:536:28 错误:找不到匹配的'construct_at(long int*&, std::_Rb_tree_const_iterator<long int>, long int)'调用。候选函数为'template<class _Tp, class ... _Args> constexpr decltype (::new(void*(0)) _Tp) std::construct_at(_Tp*, _Args&& ...)',但模板参数推导失败。/opt/wandbox/gcc-head/include/c++/14.0.1/bits/stl_construct.h:96:17 错误:new初始化表达式列表被当作复合表达式 [-fpermissive]。

解决方案

错误原因

问题核心在于ranges::to<multiset>()的模板参数推导。GCC 14对ranges::to的实现中,处理generator生成的序列时,无法自动推导multiset的元素类型,导致构造函数匹配失败。此外原代码中predecessor为空vector,后续访问会触发越界,属于潜在运行时问题。

修复步骤

  1. 显式指定multiset的元素类型
    将ranges::to<multiset>()改为ranges::to<multiset<int64_t>>(),明确目标容器的元素类型,解决模板推导错误。

  2. 添加边界检查避免越界访问
    在walk生成器函数中增加对u的范围检查,防止访问空的predecessorvector时触发未定义行为:

    while (u != 0 && u < predecessor.size())
    

修复后的完整代码

#include <vector>
#include <ranges>
#include <algorithm>
#include <functional>
#include <generator>
#include <set>
using namespace std;

struct Edge
{
    uint64_t u,v;
};

int main()
{
    // 初始化predecessor避免越界示例
    const vector<Edge> predecessor = {{0,0}, {0,0}, {1,0}}; 

    auto walk = [&](int64_t u)->generator<int64_t>{
        while (u != 0 && u < predecessor.size())
        {
            co_yield u;
            u = predecessor[u].u;
        }
    };
    
    const vector<int64_t> v={0,1,2};
    const auto ms = v |
        views::transform(walk) |
        views::join |
        ranges::to<multiset<int64_t>>() ;
    
    return 0;
}

编译命令

确保启用C++20标准编译:

g++14 -std=c++20 your_file.cpp -o your_program

内容的提问来源于stack exchange,提问作者Ludovic Aubert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 09:43:29