Passing capturing lambda as function pointer - Stack Overflow

文章推薦指數: 80 %
投票人數:10人

A lambda can only be converted to a function pointer if it does not capture, ... I am using this method in my C++ interface to F77 ODE solver RKSUITE. Resultsfromthe2022DeveloperSurveyarenowavailable Home Public Questions Tags Users Companies Collectives ExploreCollectives Teams StackOverflowforTeams –Startcollaboratingandsharingorganizationalknowledge. CreateafreeTeam WhyTeams? Teams CreatefreeTeam Collectives™onStackOverflow Findcentralized,trustedcontentandcollaboratearoundthetechnologiesyouusemost. Learnmore Teams Q&Aforwork Connectandshareknowledgewithinasinglelocationthatisstructuredandeasytosearch. Learnmore Passingcapturinglambdaasfunctionpointer AskQuestion Asked 7years,4monthsago Modified 6monthsago Viewed 218ktimes 293 84 Isitpossibletopassalambdafunctionasafunctionpointer?Ifso,ImustbedoingsomethingincorrectlybecauseIamgettingacompileerror. Considerthefollowingexample usingDecisionFn=bool(*)(); classDecide { public: Decide(DecisionFndec):_dec{dec}{} private: DecisionFn_dec; }; intmain() { intx=5; DecidegreaterThanThree{[x](){returnx>3;}}; return0; } WhenItrytocompilethis,Igetthefollowingcompilationerror: Infunction'intmain()': 17:31:error:thevalueof'x'isnotusableinaconstantexpression 16:9:note:'intx'isnotconst 17:53:error:nomatchingfunctionforcallto'Decide::Decide()' 17:53:note:candidatesare: 9:5:note:Decide::Decide(DecisionFn) 9:5:note:noknownconversionforargument1from'main()::'to'DecisionFn{akabool(*)()}' 6:7:note:constexprDecide::Decide(constDecide&) 6:7:note:noknownconversionforargument1from'main()::'to'constDecide&' 6:7:note:constexprDecide::Decide(Decide&&) 6:7:note:noknownconversionforargument1from'main()::'to'Decide&&' That'soneheckofanerrormessagetodigest,butIthinkwhatI'mgettingoutofitisthatthelambdacannotbetreatedasaconstexprsothereforeIcannotpassitasafunctionpointer?I'vetriedmakingxconstexpraswell,butthatdoesn'tseemtohelp. c++c++11lambdafunction-pointers Share Follow editedDec28,2021at18:12 CoryKramer askedFeb26,2015at15:45 CoryKramerCoryKramer 108k1515goldbadges146146silverbadges202202bronzebadges 4 54 lambdacandecaytofunctionpointeronlyiftheydon'tcaptureanything. – Jarod42 Feb26,2015at15:47 4 blogs.msdn.com/b/oldnewthing/archive/2015/02/20/10594680.aspx – BoBTFish Feb26,2015at15:49 Forposterity,theabove-linkedblogpostnowlivesatdevblogs.microsoft.com/oldnewthing/20150220-00/?p=44623 – warrenm Mar31,2020at1:24 Related:stackoverflow.com/a/9054802/4561887andstackoverflow.com/questions/25848690/… – GabrielStaples Aug11,2020at23:46 Addacomment  |  9Answers 9 Sortedby: Resettodefault Highestscore(default) Trending(recentvotescountmore) Datemodified(newestfirst) Datecreated(oldestfirst) 265 Alambdacanonlybeconvertedtoafunctionpointerifitdoesnotcapture,fromthedraftC++11standardsection5.1.2[expr.prim.lambda]says(emphasismine): Theclosuretypeforalambda-expressionwithnolambda-capturehasa publicnon-virtualnon-explicitconstconversionfunctiontopointer tofunctionhavingthesameparameterandreturntypesastheclosure type’sfunctioncalloperator.Thevaluereturnedbythisconversion functionshallbetheaddressofafunctionthat,wheninvoked,has thesameeffectasinvokingtheclosuretype’sfunctioncalloperator. Note,cppreferencealsocoversthisintheirsectiononLambdafunctions. Sothefollowingalternativeswouldwork: typedefbool(*DecisionFn)(int); DecidegreaterThanThree{[](intx){returnx>3;}}; andsowouldthis: typedefbool(*DecisionFn)(); DecidegreaterThanThree{[](){returntrue;}}; andas5gon12ederpointsout,youcanalsousestd::function,butnotethatstd::functionisheavyweight,soitisnotacost-lesstrade-off. Share Follow editedFeb14,2018at17:22 cbuchart 9,80677goldbadges4949silverbadges8181bronzebadges answeredFeb26,2015at15:49 ShafikYaghmourShafikYaghmour 149k3636goldbadges425425silverbadges714714bronzebadges 1 6 Sidenote:OnecommonsolutionusedbyCstuffistopassavoid*asthesoleparameter.It'snormallycalleda"userpointer".It'srelativelylightweight,too,butdoestendtorequirethatyoumallocoutsomespace. – Nic Nov17,2018at0:00 Addacomment  |  129 ShafikYaghmour'sanswercorrectlyexplainswhythelambdacannotbepassedasafunctionpointerifithasacapture.I'dliketoshowtwosimplefixesfortheproblem. Usestd::functioninsteadofrawfunctionpointers. Thisisaverycleansolution.Notehoweverthatitincludessomeadditionaloverheadforthetypeerasure(probablyavirtualfunctioncall). #include #include structDecide { usingDecisionFn=std::function; Decide(DecisionFndec):dec_{std::move(dec)}{} DecisionFndec_; }; int main() { intx=5; DecidegreaterThanThree{[x](){returnx>3;}}; } Usealambdaexpressionthatdoesn'tcaptureanything. Sinceyourpredicateisreallyjustabooleanconstant,thefollowingwouldquicklyworkaroundthecurrentissue.Seethisanswerforagoodexplanationwhyandhowthisisworking. //Your'Decide'classasinyourpost. int main() { intx=5; DecidegreaterThanThree{ (x>3)?[](){returntrue;}:[](){returnfalse;} }; } Share Follow editedMar8,2018at13:30 pjcard 95888silverbadges2222bronzebadges answeredFeb26,2015at16:02 5gon12eder5gon12eder 23.2k55goldbadges4343silverbadges8989bronzebadges 5 4 @T.C.Seethisquestionfordetailswhyitworks – ShafikYaghmour Feb27,2015at1:56 Notethatingeneral,ifyouknowthecapturedataatcompiletime,youcanconvertittotypedataandthenyou'rebacktohavingalambdawithnocapture-seethisanswerthatIjustwrotetoanotherquestion(thanksto@5gon12eder'sanswerhere). – dan-man Nov11,2015at0:31 Shouldn'ttheobjecthavealongerlifespanthanthepointerfunctionthen?IwouldliketouseitforglutReshapeFunc. – ar2015 Aug31,2018at12:21 idon'trecommendthissuggestion,thingsthattendtoworkmagically,introducenewerrors.andpracticesthatgoalongwiththoseerrors.ifyouwanttousestd::function,youshouldseeallkindsofwaysthatstd::functioncanbeused.becausesomewaysmaybesomethingthatyoudon'twant. – TheNegative Jul7,2019at19:19 3 Thisdoesn'tanswerthequestion.Ifonecouldusestd::functionoralambda—whywouldn'tthey?Attheveryleastit'samorereadablesyntax.UsuallyoneneedstouseafunctionpointertointeractwithClibraries(actually,withanyexternallibrary),andsureyoucan'tgomodifyittoacceptanstd::functionorlambda. – Hi-Angel Aug15,2019at15:04 Addacomment  |  59 Lambdaexpressions,evencapturedones,canbehandledasafunctionpointer(pointertomemberfunction). Itistrickybecauseanlambdaexpressionisnotasimplefunction.Itisactuallyanobjectwithanoperator(). Whenyouarecreative,youcanusethis! Thinkofan"function"classinstyleofstd::function. Ifyousavetheobjectyoualsocanusethefunctionpointer. Tousethefunctionpointer,youcanusethefollowing: intfirst=5; autolambda=[=](intx,intz){ returnx+z+first; }; int(decltype(lambda)::*ptr)(int,int)const=&decltype(lambda)::operator(); std::cout<ObjectType //RT=>ReturnType //A...=>Arguments template structlambda_expression{ OT_object; RT(OT::*_function)(A...)const; lambda_expression(constOT&object) :_object(object),_function(&decltype(_object)::operator()){} RToperator()(A...args)const{ return(_object.*_function)(args...); } }; Withthisyoucannowruncaptured,non-capturedlambdas,justlikeyouareusingtheoriginal: autocapture_lambda(){ intfirst=5; autolambda=[=](intx,intz){ returnx+z+first; }; returnlambda_expression(lambda); } autononcapture_lambda(){ autolambda=[](intx,intz){ returnx+z; }; returnlambda_expression(lambda); } voidrefcapture_lambda(){ inttest; autolambda=[&](intx,intz){ test=x+z; }; lambda_expressionf(lambda); f(2,3); std::cout<structfunction :publicfunction{}; templatestructfunction{ private: CmObject; public: function(constC&obj) :mObject(obj){} templatetypename std::result_of::typeoperator()(Args...a){ returnthis->mObject.operator()(a...); } templatetypename std::result_of::typeoperator()(Args...a)const{ returnthis->mObject.operator()(a...); } }; namespacemake{ templateautofunction(constC&obj){ return::function(obj); } } intmain(intargc,char**argv){ autofunc=make::function([](inty,intx){returnx*y;}); std::cout< #include template unionstorage { storage(){} std::decay_tcallable; }; template autofnptr_(Callable&&c,Ret(*)(Args...)) { staticboolused=false; staticstorages; usingtype=decltype(s.callable); if(used) s.callable.~type(); new(&s.callable)type(std::forward(c)); used=true; return[](Args...args)->Ret{ returnRet(s.callable(std::forward(args)...)); }; } template Fn*fnptr(Callable&&c) { returnfnptr_(std::forward(c),(Fn*)nullptr); } Anduseitas voidfoo(void(*fn)()) { fn(); } intmain() { inti=42; autofn=fnptr([i]{std::cout<func1,func2; autofn1=fnptr(func1); autofn2=fnptr(func2);//differentfunction Share Follow editedAug20,2018at13:16 answeredJul28,2017at5:51 PasserByPasserBy 18.2k66goldbadges4545silverbadges9090bronzebadges 1 1 forcingtheNintegertobedeclaredwouldbeanelegantwaytoremembertheclienttoavoidoverwritingthefunctionpointersatcompiletime. – fiorentinoing Jul23,2019at10:43 Addacomment  |  3 Notadirectanswer,butaslightvariationtousethe"functor"templatepatterntohideawaythespecificsofthelambdatypeandkeepsthecodeniceandsimple. IwasnotsurehowyouwantedtousethedecideclasssoIhadtoextendtheclasswithafunctionthatusesit.Seefullexamplehere:https://godbolt.org/z/jtByqE Thebasicformofyourclassmightlooklikethis: template classDecide { public: Decide(Functordec):_dec{dec}{} private: Functor_dec; }; Whereyoupassthetypeofthefunctioninaspartoftheclasstypeusedlike: autodecide_fc=[](intx){returnx>3;}; DecidegreaterThanThree{decide_fc}; Again,Iwasnotsurewhyyouarecapturingxitmademoresense(tome)tohaveaparameterthatyoupassintothelambda)soyoucanuselike: intresult=_dec(5);//orwhatevervalue Seethelinkforacompleteexample Share Follow answeredMay30,2020at13:20 code_foddercode_fodder 14k1212goldbadges7979silverbadges141141bronzebadges Addacomment  |  2 AshortcutforusingalambdawithasaCfunctionpointeristhis: "autofun=+[](){}" UsingCurlasexmample(curldebuginfo) autocallback=+[](CURL*handle,curl_infotypetype,char*data,size_tsize,void*){//addcodehere:-)}; curl_easy_setopt(curlHande,CURLOPT_VERBOSE,1L); curl_easy_setopt(curlHande,CURLOPT_DEBUGFUNCTION,callback); Share Follow answeredMay15,2019at9:03 janCoffeejanCoffee 36933silverbadges55bronzebadges 1 10 Thatlambdadoesn'thaveacapture.TheOP'sissueisthecapture,nothavingtodeducethefunctionpointertype(whichiswhatthe+trickgetsyou). – Sneftel May15,2019at9:07 Addacomment  |  0 Whilethetemplateapproachiscleverforvariousreasons,itisimportanttorememberthelifecycleofthelambdaandthecapturedvariables.Ifanyformofalambdapointerisisgoingtobeusedandthelambdaisnotadownwardcontinuation,thenonlyacopying[=]lambdashouldused.I.e.,eventhen,capturingapointertoavariableonthestackisUNSAFEifthelifetimeofthosecapturedpointers(stackunwind)isshorterthanthelifetimeofthelambda. Asimplersolutionforcapturingalambdaasapointeris: autopLamdba=newstd::function<...fn-sig...>([=](...fn-sig...){...}); e.g.,newstd::function([=]()->void{...} JustremembertolaterdeletepLamdbasoensurethatyoudon'tleakthelambdamemory. Secrettorealizehereisthatlambdascancapturelambdas(askyourselfhowthatworks)andalsothatinorderforstd::functiontoworkgenericallythelambdaimplementationneedstocontainsufficientinternalinformationtoprovideaccesstothesizeofthelambda(andcaptured)data(whichiswhythedeleteshouldwork[runningdestructorsofcapturedtypes]). Share Follow editedJun11,2020at19:09 answeredJul4,2018at18:37 smallscriptsmallscript 58766silverbadges1212bronzebadges 2 4 Whybotherwiththenew--std::functionalreadystoresthelambdaontheheapANDavoidsneedingtoremembercallingdelete. – ChrisDodd Jun23,2020at15:51 2 By"capturealambdaasapointer",youmeantype-eraseinsidestd::function...butOPclearlywantedafreefunctionpointer.Havingapointertostd::function,byadvisingthepointlessantipatternofrawnew,doesn'tqualifyasrelevanttotheQ. – underscore_d Jun24,2021at20:27 Addacomment  |  0 Asimularanswerbutimadeitsoyoudon'thavetospecifythetypeofreturnedpointer(notethatthegenericversionrequiresC++20): #include template structfunction_traits; template structfunction_traits{ typedefRet(*ptr)(Args...); }; template structfunction_traits:function_traits{}; template structfunction_traits:function_traits{}; usingvoidfun=void(*)(); template voidfunlambda_to_void_function(Flambda){ staticautolambda_copy=lambda; return[](){ lambda_copy(); }; } //requiresC++20 template autolambda_to_pointer(Flambda)->typenamefunction_traits::ptr{ staticautolambda_copy=lambda; return[](Args...args){ returnlambda_copy(args...); }; } intmain(){ intnum; void(*foo)()=lambda_to_void_function([&num](){ num=1234; }); foo(); std::cout<int{ num=a; returna; }); std::cout<void{YP[0]=Y[1];YP[1]=-Y[0];},TWANT,T,Y,YP,YMAX,WORK,UFLAG); Share Follow editedDec19,2015at18:42 gre_gor 6,18099goldbadges4141silverbadges4747bronzebadges answeredDec19,2015at17:38 beniekgbeniekg 7022bronzebadges 1 1 Isthisajoke?double*,double*double*double*double*...Unreadable. – DenisG.Labrecque Dec21,2020at15:15 Addacomment  |  YourAnswer ThanksforcontributingananswertoStackOverflow!Pleasebesuretoanswerthequestion.Providedetailsandshareyourresearch!Butavoid…Askingforhelp,clarification,orrespondingtootheranswers.Makingstatementsbasedonopinion;backthemupwithreferencesorpersonalexperience.Tolearnmore,seeourtipsonwritinggreatanswers. Draftsaved Draftdiscarded Signuporlogin SignupusingGoogle SignupusingFacebook SignupusingEmailandPassword Submit Postasaguest Name Email Required,butnevershown PostYourAnswer Discard Byclicking“PostYourAnswer”,youagreetoourtermsofservice,privacypolicyandcookiepolicy Nottheansweryou'relookingfor?Browseotherquestionstaggedc++c++11lambdafunction-pointersoraskyourownquestion. TheOverflowBlog Askedandanswered:theresultsforthe2022Developersurveyarehere! LivingontheEdgewithNetlify(Ep.456) FeaturedonMeta Testingnewtrafficmanagementtool Upcomingcleanupofduplicatevotes AskWizardTestResultsandNextSteps Trending:Anewanswersortingoption Updatedbuttonstylingforvotearrows:currentlyinA/Btesting Linked 7 HowtopassaLambdaFunctionasaparameter 9 Convertingalambdaexpressionwithvariablecapturetoafunctionpointer 2 error:cannotconvert‘’to‘double(*)(double)’ 1 C++Lambdacausing'candidatefunctionnotviable:' 3 UseLambdaAsArgumentInFunction 2 CanIpassaFunctorclass(thatoverloadsoperator())toafunction,thatwantsafunctionpointer?Andhow 2 Howtocaststd::functiontovoid*insidepthread_create() 3 Semantically,arelambdasrealfunctionsinC++?HowcanIpointtoalambdaexpressiontoproveit? 1 Howtogetafunctionpointerfromlambdaexpressionsorso? 2 UsingeitherablockorC++lambdaforaCfunctionpointerAPI Seemorelinkedquestions Related 819 Whatisalambda(function)? 3712 WhatarethedifferencesbetweenapointervariableandareferencevariableinC++? 2059 WhatisasmartpointerandwhenshouldIuseone? 294 Inheritingconstructors 1421 HowdofunctionpointersinCwork? 815 Distinct()withlambda? 1028 Listcomprehensionvs.lambda+filter 1702 WhatisalambdaexpressioninC++11? 1810 WhyshouldIuseapointerratherthantheobjectitself? 13 Whycan'tlambda,whencasttofunctionpointer,beusedinconstexprcontext? HotNetworkQuestions Doesmycathatemenow Canthepatentandpaperhavedifferentauthors(assumetheyincludethesamecontent)? GitPushBashscript Whyistheleft/rightspectrumdefinedsoambiguously?(Europe) Howtomakephoto-realisticlettuce? Whatdoes"CATsthreeandfour"mean? Thebestwaytopreparetheundergraduatestudentbeforeenteringthescientificresearch IssoundofUSSEnterprise’sautomaticdooropeningindeedtoiletflushingsound? Isitacceptabletoincludeinformationinaposterthatwasn'tinthepublication? Whatisthenameofthiscreature? Whydoprogunandantiabortion(andviceversa)viewsgotogetherintheUSA? TheUnaverageables WhydoIgetaccostedfortakingphotosofawarmemorial? WhatarethemainargumentsusedbyChristianpro-liferstojustifytheirstanceagainstabortion? Howtoapplyudevruletoanon-partitionedlocaldisk? Doestheemailsizelimitincludethesizeofthebody? FromwhichepisodeofTOSwasthisgifofSpockpullingclothesoutofadresserdrawertaken? Hiomneslingua:Whylinguaisputinsingular? Changeinterfacedependingonifstatement Iboughtmyfirstroadbike,andithurtsmybackandhands AfterthefallofRoevs.Wade,arewomenatriskofcriminalprosecution? "UnsupportedOS"whenusing`open`commandonM1Pro Isaclusteredindexof3columnstoobig? Primingfortheprimes morehotquestions Questionfeed SubscribetoRSS Questionfeed TosubscribetothisRSSfeed,copyandpastethisURLintoyourRSSreader. lang-cpp Yourprivacy Byclicking“Acceptallcookies”,youagreeStackExchangecanstorecookiesonyourdeviceanddiscloseinformationinaccordancewithourCookiePolicy. Acceptallcookies Customizesettings  



請為這篇文章評分?