c++boostsfinaeboost-function

Overloading of C++ functions with similar arguments


I'm trying to create two overloads of the function that takes a handler as the argument:

template <typename Handler>
void foo (Handler h);

The first overload should be called if handler takes boost::asio::yield_context as its parameter,

template <class Handler>
void foo (Handler h,
  enable_if_t<is_same<result_of_t<Handler (yield_context)>, void>::value>* = 0);

and second one should be called if handler takes boost::function as its parameter.

using func_type = boost::function<void(int,int)>;

template <typename Handler>
void foo (Handler h,
  enable_if_t<is_same<result_of_t<Handler (func_type)>, void>::value>* = 0);

Unfortunately that does not work:

main.cpp:22:3: error: call to 'foo' is ambiguous
  foo ([] (func_type f) {});
  ^~~
main.cpp:11:6: note: candidate function [with Handler = (lambda at main.cpp:22:8)]
void foo (Handler h,
     ^
main.cpp:16:6: note: candidate function [with Handler = (lambda at main.cpp:22:8)]
void foo (Handler h,
     ^
1 error generated.

Interesting, but the code works fine with std::function:

using func_type = boost::function<void (int,int)>;

As far as I understand that's because boost::function has excessive overloads for all possible calling operators, and this confuses result_of checks.

Anyway, is it possible to create the "foo" overloads that could "distinguish" between handlers taking yield_context and handlers taking boost::function as its parameters?

Coliru code: http://coliru.stacked-crooked.com/a/18344cd1b8364466


Solution

  • The standard library seems to have adopted a "moniker" argument approach:

    unique_lock<mutex> lk(std::defer_lock, mx);
    

    or

    std::pair<Foo, Foo> p1(t, t);
    std::pair<Foo, Foo> p2(std::piecewise_construct, t, t);
    

    or

    std::async(std::launch::deferred, foo, argument1);
    std::async(std::launch::async, foo, argument1);
    

    etc.

    The pattern is that

    struct defer_lock_t final { }; // for exposition
    constexpr defer_lock_t defer_lock;
    

    These "monikers" have "unique" detectable types that are guaranteed not confusable/convertible etc. with your actual argument types.