1

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 <Res(Args...)> does not compile...

0

1 Answer 1

7

There's no Function constructor that accepts a lambda. There is one that accepts an std::function, and there's also an std::function constructor that accepts a lambda, but C++ will never combine two implicit user-defined conversions for you.

The easiest way to define the needed constructor is

template <class T> Function (T&& t) : m_function(std::forward<T>(t)) {} 
Sign up to request clarification or add additional context in comments.

1 Comment

@SimonKraemer one could also remove async::Function altogether and use naked std::function instead...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.