4

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
Bonita Montero
  • 2,817
  • 9
  • 22
  • 1
    please include compiler errors in the question. Different compilers and different flags can change errors substantially – 463035818_is_not_an_ai Oct 06 '21 at 08:35
  • Somewhat related: [Converting a forwarding lambda to a function pointer](https://stackoverflow.com/questions/50428022/converting-a-forwarding-lambda-to-a-function-pointer). That one is about template argument deduction and reference collapsing. – Quentin Oct 06 '21 at 09:04

2 Answers2

4

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.

康桓瑋
  • 33,481
  • 5
  • 40
  • 90
  • I think goal of OP is to have a function pointer. That member function pointer is mostly useless... – Jarod42 Oct 06 '21 at 08:54
3

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

Jarod42
  • 203,559
  • 14
  • 181
  • 302