1

Here is the minimal reproducible code,

#include <iostream>
#include <string>

void bar(std::string s, int x){        
    std::cout <<std::endl<< __FUNCTION__<<":"<<s<<" "<<x;
}

using f_ptr = void(*)(std::string);


void foo(f_ptr ptr){        
    ptr("Hello world");
}


template<typename T> void fun(T f){
        static int x;
        std::cout <<std::endl<<x++<<std::endl;
        f("Hello World");
}

int main()
{    
    //case:1
    f_ptr ptr1 = [](std::string s){bar(s,10);}; 
   // foo(ptr1);
    
    //case:2
    static int x =10;
    f_ptr ptr2 = [x](std::string s){bar(s,x);}; 
    //foo(ptr2); 
    
    
    //case:3
    int y =10;
    f_ptr ptr3 = [y](std::string s){bar(s,y);}; /* error*/
    foo(ptr3); 
    
    //case:4
    int z = 12;
    fun([z](std::string s){bar(s,z);});
    
    return 0;
}

Error:

main.cpp:25:50: error: cannot convert ‘main()::’ to ‘f_ptr {aka void (*)(std::basic_string)}’ in initialization
         f_ptr ptr3 = [y](std::string s){bar(s,y);}; /* error*/

My questions are,

  1. Is there any way to forwards additional arguments like case:3 via lambda?
  2. What conversion is causing error in case:3?
  3. In case:4,typename T is deduced to what?
1
  • 2
    In case 2 you are not capturing anything so [x] should be just [] (basically same as case 1) while in case 3 lambda object can not be converted to pointer to normal function because it has data member y. In case 4 T is deduced to be a type of lambda. Commented Mar 2, 2021 at 7:51

2 Answers 2

2
  1. Is there any way to forwards additional arguments like case:3 via lambda?
  2. What conversion is causing error in case:3?

Lambdas with capture list can't convert to function pointer implicitly; lambdas without capture could. You can use std::function instead,

void foo(std::function<void(std::string)> f){        
    f("Hello world");
}

Or takes the lambda directly like fun does.

  1. In case:4,typename T is deduced to what?

The type would be the unique closure type; the lambda expression is a prvalue expression of that type.

Sign up to request clarification or add additional context in comments.

Comments

0

Some details, why this compiles while case 3 does not:

//case:2
static int x =10;
f_ptr ptr2 = [x](std::string s){bar(s,x);}; 

It compiles since it effectively doesn't capture anything and so the lambda can be bound to the function pointer, which is not allowed for the effective capture case. The standard says:

5.1.1/2 A name in the lambda-capture shall be in scope in the context of the lambda expression, and shall be this or refer to a local variable or reference with automatic storage duration.

So the behavior for the static variable capturing case is at least not specified, not necessarily undefined behavior though (degree of freedom for the implementation).

Be aware of the fact, that capturing static variables might lead to horrible issues in doubt since a copied value might be expected from the semantics of the capture-list but nothing is copied actually!

Also be aware of the fact, that this issue is the same for global variables (no automatic storage duration)!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.