4
votes

The problem I'm facing is straightforward. Given the following code:

template <typename ReturnType, typename... Args>
auto CallIt( ReturnType( *method )( Args... ) )
{
    return method;
}

auto test = CallIt( [] ( int a, int b )
{
    return a > b;
} );

The error that I get (using VS13 with the November 2013 CTP compiler) is:

Could not deduce template argument for ReturnType (__cdecl *)(Args...) from main::<lambda_e795bf5a030334e5fc8f3c26dbe00e0e>

I understand that a lambda is not a function pointer, but a lambda that does not capture can be assigned to a function pointer of a matching signature. If you explicitly specify the template arguments, this works. I would love to see a way where this can work without having to explicitly specify the template arguments. Thank you in advance for your help.

As noted in the comments for the answer provided by Marco A., there may be a solution to this using the unary + operator on the lambda class, effectively casting it to a function pointer. However, in the requested IDE/compiler combination I receive the following warning-turned-error:

more than one conversion function from "lambda []bool (int a, int b)->bool" to a built-in type applies:

function "lambda []bool (int a, int b)->bool::operator bool (*)(int a, int b)() const"

function "lambda []bool (int a, int b)->bool::operator bool (*)(int a, int b)() const"

function "lambda []bool (int a, int b)->bool::operator bool (*)(int a, int b)() const"

function "lambda []bool (int a, int b)->bool::operator bool (*)(int a, int b)() const"

This intellisense error sheds light on the compile error generated specifying:

error C2593: 'operator +' is ambiguous

1
Template functions get no type deduction, and converting from Lambda to a function pointer probably involves some implied conversion. See this previous question for ways around this problem.Suedocode

1 Answers

4
votes

1) Add a proper trailing return type

2) If you wish to pass a function pointer, have the lambda conform to that

template <typename ReturnType, typename... Args>
auto CallIt( ReturnType( *method )( Args... ) ) -> ReturnType(*)(Args...)
{
    return method;
}

auto test = CallIt( +[] ( int a, int b )
{
    return a > b;
} );

Live Example


Edit: it seems there's something wrong with MSVC2013. As a workaround you might try if the following works for the time being:

#include <iostream>
#include <functional>
using namespace std;

template <typename ReturnType, typename... Args>
auto CallIt( std::function<ReturnType( Args... )> method ) -> std::function<ReturnType( Args... )>
{
    return method;
}

int main() {

    std::function<bool(int,int)> lambda = [] ( int a, int b ) { return a > b; };

    auto test = CallIt( lambda );
    cout << test(4,1);


    return 0;
}

Live Example