Bonita Montero
Bonita Montero

Reputation: 3101

Get a pointer to a templated lambda operator () without captures

Can anyone tell me a valid way to get a pointer to a templated lamda (without caputes) operator () ? Already tried two alternatives:

int main()
{
    static
    auto l = []<bool a, bool b>( unsigned c ) -> unsigned
    {
        return (unsigned)a + b + c;
    };
    using fn_t = unsigned (*)( unsigned );
    fn_t fnA = &l.operator ()<true, false>; // doesn't work
    fn_t fnB = &decltype(l)::operator ()<true, false>; // also doesn't work
}

clang(-cl) 12:

x.cpp(9,13): error: cannot create a non-constant pointer to member function
        fn_t fnA = &l.operator ()<true, false> ; // doesn't work
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~
x.cpp(10,14): error: address of overloaded function 'operator()' does not match required type
      'unsigned int (unsigned int)'
        fn_t fnB = &decltype(l)::operator ()<true, false> ; // also doesn't work
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
x.cpp(4,11): note: candidate function template has different qualifiers (expected unqualified but found 'const')
        auto l = []<bool a, bool b>(unsigned c) -> unsigned
                 ^

MSVC 2019 latest update:

x.cpp(9): error C2276: '&': illegal operation on bound member function expression
x.cpp(10): error C2440: 'initializing': cannot convert from 'overloaded-function' to 'fn_t'
x.cpp(10): note: None of the functions with this name in scope match the target type

Upvotes: 4

Views: 118

Answers (2)

Jarod42
Jarod42

Reputation: 217663

It is the lambda which can be converted to function pointer in some conditions (which are not there here), not its member operator(). And you cannot convert member pointer to function pointer.

One workaround is to use another lambda.

fn_t fn = [](unsigned c) { return decltype(l){}.operator()<true, false>(c); };

Demo

Upvotes: 3

康桓瑋
康桓瑋

Reputation: 42861

The type of the address of lambda's operator() is a member function pointer, however, the definition of your fn_t is just a free function pointer. You should define your fn_t as:

using fn_t = unsigned int (decltype(l)::*)(unsigned int) const;

Then the following should work:

fn_t fnA = &decltype(l)::operator ()<true, false>;

Or, why not?

auto fnB = &decltype(l)::operator ()<true, false>;

Demo.

Upvotes: 4

Related Questions