Difference between std::generate and std::generate_n

本文介绍了如何使用C++ STL中的std::generate和std::generate_n函数来高效地生成连续序列。对比了两种方法的不同应用场景及优缺点,并给出了具体示例。

 
1. 问题:
   常常,我们编写C++程序时,需要产生 前 n 个连续的 序列:例如:1-10, 3-20 等等序列,


2. 方案
 马上想到的解决方案是:自定义一个按照顺序产生序列的 Generator,然后调用std::generate函数来产生序列并存储至容器中。


3. 资源:
  STL为我们提供了 2个generate 函数:std::generate 和 std::generate_n。如下是两个函数的声明:


   1. template <class ForwardIterator, class Generator>
   void generate(ForwardIterator first, ForwardIterator last, Generator gen);
   2. template <class OutputIterator, class Size, class Generator>
   OutputIterator generate_n(OutputIterator first, Size n, Generator gen);


  3.1 资源说明:


  相同:两个函数都是:在一个range 内,每次调用Generator生成一个值,输出到指定的Iterator指向的range 中;


   区别:两个函数需要的range不一样,

    std::generate需要两个 ForwardIterator来提供range,输入和输出range都是[First, Last),所以在输入Iterator存在之前,Container的实际内容必须存在;generator实际执行的是覆盖操作(overwrite);而不是 insert操作.


   反观std::generate 需要的参数是 OutputIterator 和 一个 N;输入range为:[0, N),输出range为:[OutputIterator, OutputIterator+N);此时输入range不需要Conatiner的存在就可以确定,所以Container的实际内容不需要存在;另外,STL提供了Insert Adapter for OutputIterator,使用Inserter,即可添加新序列至container中。


4. 结论:
  在使用变长容器时,使用 std::generate_n (Insert Adapter , N, Gen)可以提高效率。
  使用固定长度的容器时,容器的值肯定存在,两个函数的效率没区别;但是generate对容器提供的Iterator要求是:ForwardIterator 或其强化(refinement)


 

我看到你说没有提供从几何生成网格的代码以及pPreMdlParams结构体的具体格式,所以我接下来开始补充相关内容:从几何生成网格的代码如下:“日boo1 xdMesher2DHand::SurfMesh(constUintVec &srcIdxs,xdMeshParameter&mshParams,UintVec &trtMshIdxs)const try if(xdMeshTools::CheckMeshAbort ()) return false; if(m srcIdxs.empty() m srcEntLst.empty()) return true; xdmgShapeManager* pMngr = xdmgShape::Manager():xdmgAttributeManager *pAttriMngr = xdmgAttribute::Manager();if(nullptr == pMngr nullptr == pAttriMngr) return false: auto theCurModl = XdpActiveModel: auto pCsMngr = GeometryPart::Manager(theCurModl)auto pGeomApi = pCsMngr->GetApi(): auto pGeomKern = pCsMngr->GetModeler(): if(nullptr == pCsMngrnullptr == pGeomApi nullptr == pGeomKern) return false : auto bCallFunSuc = false: std::vector<xdmgFace*> srcFacLst: std::vector<std::string> tmpSrcFacUuids; // Revised by IvenLuo at 15:48, 2021/07/13. /for selected faces mesh std::vector<xdmGeomId>selFacUuids; // Revised by IvenLuo at 15:12, 2021/07/28. //temp use HexComponents == 3 means selected part faces mesh auto bSelFacMesh = mshParams.GetMeshSelectedGeometry():GetSelectEntityUuids(selFacUuids, bSelFacMesh):if(!selFacUuids.empty()) std::vector<xdmGeom>selSpltFacs:bCallFunSuc = xdMeshTools::GetPrepareFaces(selFacUuids, selSpltFacs) srcFacLst.reserve(selSpltFacs.size()); for(auto orgFac :selSpltFacs) auto pFac =dynamic cast<xdmgFace*>(pMngr->0bject(orgFac)):srcFacLst.emplace back (pFac): else for(auto bdy :m srcEntLst) auto shp = pMngr->0bject (bdy): if (shp != nullptr) ListFace bdyFaces. shp->Faces(bdyFaces):if(!bdyFaces.empty()) srcFacLst.insert(srcFacLst.end(),bdyFaces.begin(), bdyFaces. end()) Revised by IvenLuo at 22:27, 2024/05/26. do not use 0CCMODEL mac 1发 (pGeomKern->GetNativeKernel()== BaseModeler::0ccKernel){... } 1 (m_meshParams.GetVerboseType()>= XDM VERBOSE _DEBUG) if(m meshParams.GetProcessldx():-1mmeshParams.GetProcessIdx()== 0) std::string wirInfo = "Total input surface number of prepared model = "+ to_string(srcFacLst. size()+ "\n" ListEdge facEdgs: ListVertex facVtxs.//for(auto fac : srcFacLst) ML I#if A fac->Vertices(facVtxs) fac->Edges(facEdgs): #endif for(auto bdy :m srcEntLst) auto shp = pMngr->0bject(bdy):if(shp != nullptr) shp->Edges(facEdgs):shp->Vertices (facVtxs) std::unordered set<xdmgEdge*> allEdgs: std::unordered set<xdm gVertex*> allVtxs (auto pFac srcfaclst facEdgs. clear();pFac->Edges(facEdgs):allEdgs.insert(facEdgs.begin(), facEdgs. end()): for (auto pEdg : facEdgs) allVtxs.insert(pEdg->GetStartVertex())allVtxs.insert(pEdg->GetEndVertex()): //facEdgs. sort(): //facEdgs. unique () . /facVtxs.sort(): /facVtxs. unique() wirInfo += "Total input edge number of prepared model ="+ to_string(allEdgs. size())+ “\n".wirInfo += "Total input vertex number of prepared model = "+ to_string(allVtxs.size())+ "\n” if(m meshParams.GetProcessNum()>0) xdMeshTools::PrintMessage2Log(wirInfo): else xdMeshTools::PrintMessage(wirInfo): //#endif if(!m srcEntLst.empty()) // Revised by IvenLuo at 10:14,2021/04/15.// bug #1082, get default box with filtering wire body//auto bCallFunSuc = XDMGeomAPI_GetBox(m_srcEntLst.first(), nullptr, m_srcBox)m srcBox= GetDefaultMeshBox(srcIdxs, m srcEntLst[0]/*,m_srcBdyTypes*/); /int cnt =-1. //std::set<int>fltTrtFacPosSet = { 0 }: //if(m_meshParams.GetVerboseType()< XDM_VERBOSE_DEBUG) M fltTrtFacPosSet.clear():TT IA double plnTol = TOL PO2: bool bIsPln = false:std::vector<xdmGeom>srcFacs: srcFacs.reserve(srcFacLst.size());for(auto face : srcFacLst) //++cnt ; // Revised by IvenLuo at 16:21, 2020/12/02. support portion or multi-mesh if(m meshParams.GetRefinelterationNum()== 0 && XDML CLEAR NO MESH GEOMETRY TYPE == m meshParams. GetclearDBrype()) // temp use this option meaning no clean original mesh auto facMsh = dynamic cast<xdmgAttrMesh*>(pAttrilngr->pindttribute(face, xdmgAttrlesh:Name(0)/*, true*/): // need to load from geometry?? bool needMesh = false if 0 if (facMsh != nullptr)// had been meshed ahead, skip this face std::vector<UINT> elms;facMsh->GetBlements(elms) for (auto elm :elms) if(femElement::Manager()-)UsageFlag(elm)== xdp::objectDeleted) needMesh = true; break: if(!needMesh) continue. //// for testing//if(m meshParams.GetVerboseType () == XDM VERBOSE DEBUG)1E if(!fltTrtFacPosSet.empty()&& fltTrtFacPosSet,find(cnt)== fltTrtFacPosSet.end()) continue ; IA //// end testing endif /Revised by Ivenluo at 14:55, 2022/06/15. check plane and cached its normal if face is planeauto bIsPln=face->IsSimilarPlane(plnTol): srcFacs.emplace back(face->GetSourceGeom())m_srcFacs.insert(face): if(m meshParams.GetVerboseType()>= XDM _VERBOSE DEBUG){... xdmSurfMeshParameter surfOpts:bCallFunSuc =SetMeshParameters(mshParams,surfOpts) xdMeshLocalSizeMapfacToLocSizMap xdMeshLocalSizeMapedgToLocSizMap xdMeshLocalSizeMap vrtToLocSizMap:std::map<xdmGeom, xdmPointVec>edgToFixPtsMap: /Revised by Ivenluo at 11:47,2023/08/24.//set local mesh size or uniformly mesh for large face with single loop 1.± (xdMeshParameter::GetAppMeshField()== XDM CEM MESH FIELD1年 &&mshParams.GetFrequency()>0) bCallFunSuc =SetUniformLocalMeshForCEM(srcFacs,facToLocSizMap,mshParams): endif bCallFunSuc =GetMeshLocalSize(srcFacs,facToLocSizMap,edgToLocSizMapvrtToLocSigMap)bCallFunSuc = GetSplitEdgeFixPoints(srcFacs, edgToFixPtsMap): xdMeshLocalSizeMap edgToLocSizMap2 ;xdMeshLooplayerMap edgToLooplayerMap;std::vector<void*〉 allFreeEdges: auto GetAllFreeEdges =[&](std::vector<void*>&tmpAllFreeEdges)-> bool std::set<void*> allEntEgds.std::set<void*> allFacEdgs : for (auto ent :m srcEntLst) auto pBdyPtr =pGeomKern->GetEntityWrapper(ent):if(nullptr == pBdyPtr) continue; std::vector<IEdgePtr> entEdgs.pBdyPtr->GetAllEdges(entEdgs)allEntEgds.insert(entEdgs.begin(),entEdgs.end()) for (auto pEdgPtr : entEdgs) allEntEgds.insert (pEdgPtr->GetEntityPointer()): std::vector<IFacePtr> entFacs:pBdyPtr->GetAllFaces(entFacs)for(auto afac : entFacs) entEdgs.clear():afac->GetAllEdges(entEdgs):for(auto pEdgPtr : entEdgs) allFacEdgs.insert(pEdgPtr->GetEntityPointer()). std:set difference(allEntEgds. begin(0), allEntEgds. end0, allFacEdgs, begin0, allFacEdgs, end(), std::back inserter(tmpAllreeEdges)):return true; GetAllFreeBdges(allFreeEdges):if(surfOpts.GetTriQuadType()== 1) bCallFunSuc = GetLoopMeshData(srcFacs, edgToLocSizMap2, edgToLoopLayerMap): auto AddlooplayerSizeToLocalMeshSizeMap = [&] (xdeshlocalSizeap& edgeToLocalMeshap, const xdMeshlocalSizeMap& edgeToLoopLayerMap)->void auto pMngr =(xdmgShapeManager*)xdmgShape::Manager(): if(pMngr == NULL) return; for (auto currGeom : edgeToLoopLayerMap) if (std: :find(edgeToLocalMeshMap. begin(), edgeToLocalMeshMap.end(), currGeom)!= edgeToLocalMeshMap. end())continue: xdmgEdge* aEdge =(xdmgEdge*)pMngr->0bject(currGeom.first) double edgeLenaEdge->Length() currGeom.second +0.5)int segNumint(edgeLen if(segNum< 1)segNum=1. if(segNum %2 != 0) ++segNum: edgeToLocalMeshMap,insert(std::make pair(currGeom. first, double(segNum))): AddLoopLayerSizeToLocalMeshSizeMap(edgToLocSizMap,edgToLocSizMap2): xdMeshLocalSizeMap faceToAngMapxdMeshLocalSizeMap edgeToAnMap :bCallFunSuc = GetMeshLocalGeometricApproximateAngle(srcFacs, faceToAngMap, edgeToAnMap). /added by hyh at 2022/03/31 for PEc facesstd::vector<xdmGeom>pecFaces. if(!surfOpts.GetGeomConvertMesh ()) if(surfOpts. GetUseEdgingMesh()) bCallFunSuc =GetPECFaces(pecFaces): if(facToLocSizMap.empty()&& edgToLocSizMap. empty()&& vrtToLocSizMap. empty()&& faceToAngMap.empty()&& edgeToAnMap. empty() && pecFaces.empty() && edgToFixPtsMap. empty()) bCallFunSuc=SurfaceMeshAPI(srcFacs, surfOpts): else std::vector<double> faceSizeVect :faceSizeVect.reserve(srcFacs.size())const double noSetFacLocSiz = 0.0:for(auto srcFac :srcFacs) auto itrFnd = facTolocSizMap.find(srcFac)if(itrFnd != facToLocSizMap. end()) faceSizeVect.emplace back(itrFnd->second) else faceSizeVect.emplace back(noSetFacLocSiz) bCallPunSuc = SurfaceMeshWithDiffSizeAPI(srcFacs, faceSizeVect, edgToLocSizMap, vrtToLocSizMap,edgToLoopLayerMap, faceToAngMap, edgeToAnMap, pecFaces, edgToFixPtsMap, surfOpts): if(!bCallFunSuc) DEBUG #ifdef xdMeshTools::PrintMessage("Call SurfaceMeshAPI () failed! \n”)// ifdef DEBuG #endif return false; void* PyObject= TheApp.RunStringArg(xfmApp::False,cem. GetWireUuidList()”)void* PyObject = nullptr:if(xdMeshParameter::GetAppMeshField()== XDM CEM MESH FIELD) PyObject = xdMeshTools::RunStringArg("cem, GetWireUuidlist()", false, true) bool doWireMesh = false. if(Pyobject) doWireMesh = xfmPyTool::Parser<bool>()(PyObject): xdmGeomVector toBdyMeshEdges(allFreeEdges.begin(), allFreeEdges. end ()):if(dowireMesh) xdmGeomVector srcAllEdges: xdmGeomVector srcEdgeToMeshList ;std::vector<xdmGeomId>edgToMeshLst : std::vector<double> tmpParamLst: int intbuffer =0: xfmUiDataBuffer *curbuffer = xdMeshTools::GetCurrentBufferData(): std::vector<std::string> vPosLst: curbuffer->GetVecotr("GeometryPos", vPosLst): curbuffer->GetIntVector("GeometryID",edgToMeshLst) assert(vPosLst.size()== edgToMeshLst.size()): //curbuffer->GetInt( EdgeCount", &intbuffer):curbuffer->Pop(): intbuffer = edgToMeshLst.size(): if(intbuffer >0) for(int i=0:i< intbuffer: ++i) tmpParamLst.push back(stof(vPosLst[i])) std::unordered map<xdmGeomId,double> tmpWirPortParamMap:tmpWirPortParamMap,reserve(edgToMeshLst,size()).for(int i=0:i< edgToMeshLst.size(): i++) tmpWirPortParamMap, insert(std::pair<xdmGeomId, double>(edgToMeshlst[i], tmpParamLst [i])): std::sort(edgToMeshlst.begin(), edgToMeshLst.end () ):auto tmpItr = std::unique(edgToMeshLst.begin(), edgToMeshLst. end())edgToMeshLst.erase(tmpItr, edgToMeshLst.end()): std::vector<double> newTmpParamLst : newTmpParamLst.reserve(edgToMeshLst. size ()):for (int i=0:i<edgToMeshLst,size(:i++ newTmpParamLst. push back(tmpWirPortParamMap[edgToMeshLst[i]]) std::set<void*> edgObjToMeshLstfor (auto uuid : edgToMeshlst) edgObjToMeshLst.insert(pGeomApi->GetEntity(uuid)->GetEntityPointer ()): std::vector<xdmgEdge*> srcEdgListfor (auto bdy :m srcEntLst) auto shp = pMngr->0bject (bdy):if (shp != nullptr) ListEdge bdyEdges: shp->Edges (bdyEdges)srcEdgList.insert(srcEdgList.end(),bdyEdges.begin(), bdyEdges. end()). for (auto tmpEdg : srcEdgList)std::vector<xdmGeomId>tmpSrcNames:bool tSuc = xdMeshTools::GetEntityAllTraceNames(tmpEdg->GetSourceGeom(), false, tmpSrcNames)if(tSuc) std::set<void*> tmpSrcObjectsLst;for(auto uuid : tmpSrcNames) tmpSrcObjectsLst.insert(pGeomApi->GetEntity(uuid)->GetEntityPointer()):std::vector<void*> tmpCmnStrLst;std::set<std::string> tmpSelecteddgUuidSet(edgToMeshlst.begin(), edgToMeshlst. end()):std::set<std::string》tmpSrcNamesSet(tmpSrcNames,begin(), tmpSrcNames.end()).std:: set_intersection(edgOb jToMeshlst. begin(), edg0b jToMeshlst. end(), tmpSrc0b jectsLst. begin(), tmpSrc0b jectsLst. end(),std::back inserter(tmpCmnStrLst))if(!tmpCmnStrLst.empty()) srcEdgeToMeshList.push back(tmpEdg->GetSourceGeom()): /std::vector<std::string >allNames cmtBox partBox:pGeomApi->GetModelBoundingBox0fCurrentSln(nullptr, partBox, false)auto siz= partBox,Corner(0).DistTo(partBox, Corner(7)); double tollerance = 1.0B-6 * siz; //merge from main branch of SvN 9212 - endauto myEdgeListSort =[pGeomKern, pGeomApi](void* edgl, void* edg2)->bool auto pLftGeomPtr = pGeomKern->GetEntityWrapper(edg1)auto pRghGeomPtr= pGeomKern->GetEntityWrapper(edg2): if(nullptr == pLftGeomPtrnullptr == pRghGeomPtr) return false; xdmGeomId lftUuid, rghuuid:pGeomApi->GetEntityID(pLftGeomPtr, lftUuid)pGeomApi->GetEntityID(pRghGeomPtr, rghUuid)return lftUuid< rghUuid; std::sort(srcEdgeToMeshlist.begin(),srcEdgeToMeshlist.end(), myEdgeListSort). merge from main branch of SN 9212-endstd::vector<double>hardPntParamLst: if(edgToMeshlst.size()>0) std::vector<xdmGeom>srcWireGeomListfor(auto tmpEdg : srcEdgeToMeshlist) auto tmpEdgPtr=pGeomKern->GetEdgeWrapper(tmpEdg)std::vector<xdmGeomId>tmpSrcNames:xdMeshTools::GetEntityAllTraceNames(tmpEdg, false, tmpSrcNames):// check if there are intersection between tmpSrcNames and edgToMeshLst std::list<xdmGeomId> tmpLst1:std::list<xdmGeomId>tmpLst2 for (autosrcNamtmpSrcNames) auto srcEdg= pGeomApi->GetEdge(srcNam):for(int i=0:i<edgToMeshLst.size():++i) auto srcEdgObj= pGeomApi->GetEdge(edgToMeshLst[i])://1. check if there is middle hard point //if(srcEde == srcEdeob i)if(srcEdg->IsSameAs(srcEdg0bj)) srcWireGeomlist.push back(tmpEdg): //calculate position on original edge and project on split edge/then, calculate the param value of the project pnt on split edgedouble srcUMin, srcUMax:srcEdg->GetParamBound(srcUMin,srcUMax)double realParam= srcUMin + newTmpParamlst[i]*(srcUMax- srcUMin)cmtPoint tPt: srcEdg->GetPositionByParam(realParam, tPt): cmtPoint prjPnt.double prjParam :tmpEdgPtr->GetParam(tPt, prjParam, /*tollerance,*/prjPnt)double uMin, uMax:tmpEdgPtr->GetParamBound(uMin,uMax):double prjUnitParam =(prjParam -uMin)/(uMax - uMin): if (prjUnitParam >= 1.08-3 && prjUnitParam<=1.0- 1.0E-3 /*&& tPt.DistTo(prjPnt)<= tollerance*/)hardPntParamLst.push back (prjUnitParam) :else if(prjunitParam< 1.0E-3) hardPntParamLst.push back(0.0): else hardPntParamLst. push back(1.0) ifdef DEBuG endif if(m meshParams.GetVerboseType()>= XDM VERBOSE DETAIL) std::string wirInfo = "wire edges count to be meshed: " + to string(srcWireGeomlist.size())+ "\n"xdMeshTools::PrintMessage(wirInfo): std::set<void*》toMeshEdgeSet(srcWireGeomlist.begin(), srcWireGeomList.end())std::set<void*>allFreeEdgeSet(allFreeEdges.begin(), allFreeEdges.end()):toBdyMeshEdges.clear():std:;set difference(allFreeEdgeset.begin(), alFreedgeSet. end(), toMeshedgeset.begin0, toMeshedgeet. end0, std:back inserter(toBdyleshdges)bCallFunSuc = WireMesh(srcWireGeomlist, hardPntParamLst, true)if(!bCallFunSuc) ifdef DEBUG xdMeshTools::PrintMessage( Call SurfaceMeshAPI() failed!\n”)endif // ifdefDEBUG return false; // Revised by IvenLuo at 11:10, 2022/06/19./currently, ignore free edge mesh for FEM#if 0 xdMeshParameter orgMshOpts:assert(m pCurMshLog != nullptr):if(m pCurMshlog != nullptr) m pCurMshLog->GetMeshParameter(orgMshOpts) if(orgMshOpts.GetMeshType()!= XDM SOLID_TET MESH TYPE) if(!toBdyMeshEdges. empty()) if(selFacUuids. empty()) // if there are free edges and they are not wire mesh objects, discrete them with bdy mesherbCallFunSuc=WireMesh(toBdyMeshEdges, std::vector<double>(), false): /#endif UintVec trtBlmIdxs: xdmTypeToElementsMap typToElmsMap:bCallFunSuc =RealCreateBlments(mgFacMsh, typToElmsMap, trtElmIdxs)if(!bCallFunSuc) //#ifdef DEBUG xdMeshTools::PrintMessage("Call RealCreateElments()failed! \n”)//#endif // ifdef DEBuG return false; '/ Revised by IvenLuo at 15:01, 2021/10/07. // delete nodes in SurfaceMeshAPI()may include free nodes of wire mesh//such as quad mesh without inner wire nodes constrain(bug #2241) // delete free nodes (occ bug #2155)auto PNums =mshParams.GetProcessNum(): if(PNums ==-1|m meshParams. GetProcessIdx()==0) auto freNdNum = theFemlib.DeleteUnRefNodes (): #ifdefDEBUGif(freNdNum >0) /xdMeshParameter newMshOpts//if(m_pCurMshLog != nullptr) IL mpCurMshLog->GetMeshParameter(newMshOpts) IA //if(newMshOpts.GetVerboseType()>= XDM_VERBOSE DEBUG) std::string strDebugMsg = "Warning: There are " + to_ string(freNdNum) + " free nodes that have been deleted!\n"xdMeshTools::PrintMessage(strDebugMsg): /assert (false): endif /Progress Status:80% for surface apixdMeshTools::SetProgValue(80); build mesh element<--> surface map tifdefDEBUG I号(m meshParams.GetVerboseType()>= XDM VERBOSE DETAIL) xdMeshTools::PrintMessage("Building Wire Mesh Relation!\n”): tendif bCallFunSuc = BuildSurfElmentRelation(trtMshIdxs): auto bMshBoolPre = mshParams.IsMeshBooleanPrepare()//revised by hyh at 2023/09/20 if(!bMshBoolPre &&mshParams.GetMeshType ()== XDM SURF TRI MESH TYPE // skip clean for quad mesh && mshParams.GetSurfIntersectCorrect()) XdMeshCleanUpAPI RepairMesh (): //Revised by IvenLuo at 11:40,2023/02/22. /mesh boolean without geometry non-regular boolean prepare if(bMshBoolPre){... /Progress Status:95% for surface api xdMeshTools::SetProgValue(95): //Revised by IvenLuo at 21:56,2021/03/29. //UintVec edgVtxMshIdxs ; //bCallFunSuc =BuildEdgeElementRelation(edgVtxMshIdxs) //bCallFunSuc=BuildVertexElementRelation(edgVtxMshIdxs): return bCallFunSuc : catch(...) std::string strExceptMsg("XD surface mesh failed with unhandled exception!\n”)xdMeshTools::PrintMessage(strExceptMsg): return false: ”,pPreMdlParams结构体的格式如下:“struct LayoutPrepMdlLayerParams { int id; // 压片层ID double dEvalLower; // 层高度 double dThickness; // 层厚度 std::vector<int> lstShapesIds; // 该层包含的形状ID列表 }; using LayoutPath = std::vector<cmtPoint2D>; // 2D点(x,y)组成的路径 struct LayoutPolygon { LayoutPath path; // 多边形边界路径 std::vector<LayoutPath> holes; // 多边形内部的孔洞 std::vector<int> owner_shape_ids; // 所属形状ID }; struct LayoutPrepMdlParams { std::vector<LayoutPolygon> Bodies; // 多边形集合 std::vector<LayoutPrepMdlLayerParams> Layers; // 层参数集合 }; ”
10-17
### C++ 中 `std::generate` 函数的用法 `std::generate` 是 C++ 标准库中的一个算法,用于填充容器的内容。该函数接受两个迭代器范围以及一个生成器函数或可调用对象作为参数,并依次对该范围内每个元素赋值。 语法如下: ```cpp #include <algorithm> #include <vector> namespace { template<typename ForwardIt, typename Generator> void generate(ForwardIt first, ForwardIt last, Generator g); } ``` 此函数会反复调用给定的生成器 `g()` 并将返回的结果存储到 `[first, last)` 范围内的每一个位置上[^1]。 下面是一个简单的例子来展示如何使用 `std::generate` 来初始化向量中的元素: ```cpp #include <iostream> #include <vector> #include <algorithm> // For std::generate #include <functional> // For std::ref // A simple generator function that increments an internal counter each time it's called. class CounterGenerator { private: int value; public: explicit CounterGenerator(int startValue = 0) : value(startValue) {} int operator() () { return ++value; } }; void demonstrateGenerateWithFunctionObject() { std::vector<int> numbers(5); CounterGenerator gen; std::generate(numbers.begin(), numbers.end(), gen); for (auto num : numbers) { std::cout << num << ' '; } // Output should be something like: 1 2 3 4 5 } /// Using lambda expression as a generator with std::generate void demonstrateGenerateWithLambdaExpression() { std::vector<std::string> names{"Alice", "Bob"}; auto randomNamePicker = [&names]() -> std::string& { static thread_local std::mt19937 rng(std::random_device{}()); std::uniform_int_distribution<> dist(0, names.size()-1); return names[dist(rng)]; }; std::vector<std::reference_wrapper<const std::string>> selectedNames(3); std::generate(selectedNames.begin(), selectedNames.end(), std::cref(randomNamePicker())); for(auto&& nameRef : selectedNames){ std::cout<<nameRef.get()<<'\n'; } } ``` 上述代码展示了两种不同类型的生成器:一个是类成员函数重载了 `operator()` 的方式;另一个则是通过 Lambda 表达式实现随机选取字符串的功能。这两种方法都可以很好地配合 `std::generate` 使用[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值