Poperton
Poperton

Reputation: 2148

Type of lambda function that receives an argument

I'm trying to receive lambda functions as parameters, however I'm having problem with its types.

Here's how I'm calling the function

profile(0, 1000, fps, [](ProfilerVariable<int> &fps){fps.counter++;}, [](ProfilerVariable<int> &fps){fps.counter=0;});

Here's how I defined it:

template <typename T>
void profile(int index, int intervalInMilliseconds, ProfilerVariable<T>& profilerVariable,
                 std::function<void(ProfilerVariable<T>&)> const &increaseFunction, 
                 std::function<void(ProfilerVariable<T>&)> const &resetFunction)
    {
            increaseFunction(profilerVariable);
            //...

I don't see nothing wrong. Return type is void, and it accepts ProfilerVariable&:

    /home/dev/orwell/cpp/common/ZLRTSPClient.cpp:38:26: error: no matching function for call to 'ZLRTSPClient::profile(int, int, ProfilerVariable<int>&, ZLRTSPClient::init()::<lambda(const toolkit::SockException&)>::<lambda(const Ptr&)>::<lambda(ProfilerVariable<int>&)>, ZLRTSPClient::init()::<lambda(const toolkit::SockException&)>::<lambda(const Ptr&)>::<lambda(ProfilerVariable<int>&)>)'
                         });
                          ^
In file included from /home/dev/orwell/cpp/common/RTSPClient.h:11:0,
                 from /home/dev/orwell/cpp/common/ZLRTSPClient.h:3,
                 from /home/dev/orwell/cpp/common/ZLRTSPClient.cpp:1:
/home/dev/orwell/cpp/common/Profiler.h:41:10: note: candidate: template<class T> void Profiler::profile(int, int, ProfilerVariable<T>&, const std::function<void(ProfilerVariable<T>&)>&, const std::function<void(ProfilerVariable<T>&)>&)
     void profile(int index, int intervalInMilliseconds, ProfilerVariable<T>& profilerVariable,
          ^~~~~~~
/home/dev/orwell/cpp/common/Profiler.h:41:10: note:   template argument deduction/substitution failed:
/home/dev/orwell/cpp/common/ZLRTSPClient.cpp:38:26: note:   'ZLRTSPClient::init()::<lambda(const toolkit::SockException&)>::<lambda(const Ptr&)>::<lambda(ProfilerVariable<int>&)>' is not derived from 'const std::function<void(ProfilerVariable<T>&)>'
                         });
                          ^

PS: what does the const in std::function<void(ProfilerVariable<T>&)> const &increaseFunction stands for?

Upvotes: 1

Views: 110

Answers (1)

Jarod42
Jarod42

Reputation: 217275

lambda is not std::function, so T cannot be deduced.

You might get rid of std::function and take functor:

template <typename T, typename F1, typename >
void profile(int index,
             int intervalInMilliseconds,
             ProfilerVariable<T>& profilerVariable,
             F1 const &increaseFunction,
             F2 const &resetFunction) {/*..*/}

or you can make those parameters non deducible:

template <typename T>
void profile(int index,
             int intervalInMilliseconds,
             ProfilerVariable<T>& profilerVariable, // Deduce T only here
             std::type_identity_t<std::function<void(ProfilerVariable<T>&)>> const &increaseFunction, 
             std::type_identity_t<std::function<void(ProfilerVariable<T>&)>> const &resetFunction)

std::type_identity_t is C++20 but can be implemented for previous version.

Else you have to change in the call site

  • be explicit:

    profile<int>(0, 1000, fps, [](ProfilerVariable<int> &fps){fps.counter++;}, [](ProfilerVariable<int> &fps){fps.counter=0;});
    
  • or use "correct" arguments

    profile(0,
            1000,
            fps,
            std::function{[](ProfilerVariable<int> &fps){fps.counter++;}},
            std::function{[](ProfilerVariable<int> &fps){fps.counter=0;}});
    

Upvotes: 2

Related Questions