How to check whether, given the argument types, an implicit use of `operator ()` would result in exactly one best viable candidate?

As I understand it, the outcome of a function name usage might be one of the following:

  1. There are no (best) viable functions — overload resolution fails. The suboutcomes are:
    1. There are no candidates.
    2. There are some candidates, just none are viable.
  2. There is exactly one best viable function — overload resolution succeeds. The selected overload is then either
    1. OK — the overall call is well-formed.
    2. not OK (= deleted, protected/private or, perhaps, something else) — the overall call is ill-formed.
  3. There are more than one best viable functions — overload resolution fails with ambiguity.

The question is: How to reliably tell apart outcome #2.2 (at least some of its cases) from outcomes #1.2 and #3 (at least one of them) in the case of implicit usage of operator () (i.e. c(a...)) by means of a type trait that accepts the types of the arguments (including c) to be used in the call?

(I’m not interested in outcomes #1.1 and #2.1 as I know that #1.1 does not hold in my particular use case and #2.1 is easily detectable through SFINAE.)


A specific example. How to implement a type trait that looks something like the following

/// Would `c(a...)` result in exactly one best viable candidate?
/// (Where `decltype(c)`, `decltype(a)...` are `C`, `A...`, respectively.)
template<class C, typename... A>
inline constexpr bool has_exactly_one_best_viable_call_candidate;

so the following asserts hold?

struct WithNoViable {
    void operator ()(void *);
};

struct WithDeleted {
    void operator ()(long) = delete;
};

struct WithAmbiguity {
    void operator ()(long);
    void operator ()(long long);
};

static_assert(!has_exactly_one_best_viable_call_candidate<WithNoViable, int>);
static_assert( has_exactly_one_best_viable_call_candidate<WithDeleted, int>);
static_assert(!has_exactly_one_best_viable_call_candidate<WithAmbiguity, int>);

Note that in general nothing is known about the types of parameters nor arguments.

Source: Windows Questions C++

LEAVE A COMMENT