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