0

If I have a function with variable arguments, with one of them being a callback function, how would the bind function for that work? Current implementation as below:

template <typename... Args>
bool CallWithArgs(std::function<void (String&, Args... args)> cbk, Args... args) 
{ .... }

The above function is being called from a separate class using a future:

bool value = true;
auto f1 = std::bind(&CallWithArgs, rawPtr, _1, _2);
std::future<bool> fut = std::async(f1, cbk, value);
fut.wait();

Is there anyway to represent variable parameters in the placeholders of the std::bind function? Running into compile issues with the present implementation.

note: template<class _Func, class ... _BoundArgs> typename std::_Bind_helper<std::__or_<std::is_integral<typename std::decay<_Tp>::type>, std::is_enum<typename std::decay<_Tp>::type> >::value, _Func, _BoundArgs ...>::type std::bind(_Func&&, _BoundArgs&& ...)
     bind(_Func&& __f, _BoundArgs&&... __args)

note:   template argument deduction/substitution failed:
note:   couldn't deduce template parameter ‘_Func’
6
  • 1
    Have you considered using a lambda instead? (On second thought: you probably need C++14) Commented Mar 12, 2019 at 15:05
  • 1
    Is this a purely academic question, or are you trying to get something working? If it's the later, the answer is simple: just use a lambda instead. Commented Mar 12, 2019 at 15:05
  • I am trying to get something working. The only issue with using a lambda is that the function with variable args is part of a common library. So making it a lambda and putting it in the class where I am calling it would not be feasible. Commented Mar 12, 2019 at 15:09
  • @PK17 It's unclear to me why putting lambda in a class would be less feasible than std::bind. Commented Mar 12, 2019 at 15:17
  • @eerorika As I mentioned the CallWithArgs fn is part of a common library and needs access to other functions/variable within that common library. And I plan to further allow the support to calling that function from other components/executables. Dont want every component implementing the same fn CallWithArgs as a lambda function. Commented Mar 12, 2019 at 15:22

1 Answer 1

1

Since you can't use C++14's generic lambdas you can make your own by making a functor. If you have

struct CallWithArgsFunctor
{
    pointer_type pointer_to_call_on;
    CallWithArgsFunctor(pointer_type pointer_to_call_on) : pointer_to_call_on(pointer_to_call_on) {}
    template<typename... Args>
    auto operator()(Args&&... args) -> decltype(CallWithArgs(pointer_to_call_on, std::forward<Args>(args)...))
    {
        return CallWithArgs(pointer_to_call_on, std::forward<Args>(args)...)
    }
};

then you can use it in your code block like

bool value = true;
std::future<bool> fut = std::async(CallWithArgsFunctor{rawPtr}, cbk, value);
fut.wait();

This allows overload resolution to work in the body of the call operator instead of you having to cast the function pointer to the type you want to call.


If you can upgrade to C++14 your code would just become

bool value = true;
auto f1 = [=](auto&&... args){ return CallWithArgs(rawPtr, std::forward<decltype(args)>(args)...); };
std::future<bool> fut = std::async(f1, cbk, value);
fut.wait();
Sign up to request clarification or add additional context in comments.

4 Comments

Upgrading to c++14 would be nice yes :) But unfortunately that's not possible at this time. Will try your suggestion of using a functor and update here. Thanks!
@PK17 No problem. Let me know if it works for you.
Thanks @NathanOliver Your suggestion worked. Also created a separate test file to try out the C++14 way and that works too!
@PK17 Awesome. Glad it works for you. Hopefully one day you can upgrade :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.