lundi 26 mars 2018

Cannot construct from lambda

I'm stuck with a compilation problem. I do not understand why the following code does not compile:

#include <functional>

namespace async {

template<class ...T>
using Callback = std::function<void(const std::string& result, T ...args)>;

template<class Signature>
class Function;

template<class Res, class ...Args>
class Function<Res(Args...)>
{
    std::function<void(Args ...args, const Callback<Res>&)> m_function;
public:
    Function(std::function<void(Args ...args, const Callback<Res>&)>&& function) : m_function(std::move(function)) {}
    Function& operator=(std::function<void(Args ...args, const Callback<Res>&)>&& function) {m_function = std::move(function); return *this;}
    void operator()(Args... args, const Callback<Res>& callback) const {m_function(args..., callback);}
};

}

async::Function<int(int)> getF()
{
    return [](int i, const async::Callback<int> callback)
    {
        callback("", i);
    };
}

int main(int argc, char** argv)
{
    auto f0 = getF();
    return 0;
}

gcc says:

In function ‘async::Function getF()’: error: could not convert ‘getF()::__lambda0{}’ from ‘getF()::__lambda0’ to ‘async::Function’

icc says:

error: no suitable user-defined conversion from "lambda [](int, async::Callback)->void" to "async::Function" exists

Now if I replace

    return [](int i, const async::Callback<int> callback)
    {
        callback("", i);
    };

by

    return async::Function<int(int)>([](int i, const async::Callback<int> callback)
    {
        callback("", i);
    });

Then it works. Why to I need to cast explicitely and how to avoid this?


A simpler solution would be to replace the class Function by something like

template<class Signature>
using Function = std::nullptr_t;

template<class Res, class ...Args>
using Function<Res(Args...)> = std::function<void(Args ...args, const Callback<Res>&)>;

But the specialization with does not compile...

Aucun commentaire:

Enregistrer un commentaire