如何检查给定参数类型,隐式使用“operator ()”是否会产生一个最佳可行候选者?

rad*_*dix 6 c++ well-formed ambiguous-call language-lawyer overload-resolution

据我了解,函数名称使用的结果可能是以下之一:

\n
    \n
  1. 没有(最佳)可行的函数 \xe2\x80\x94 重载解析失败。子结果是:\n
      \n
    1. 没有候选人。
    2. \n
    3. There are some candidates, just none are viable.
    4. \n
    \n
  2. \n
  3. There is exactly one best viable function \xe2\x80\x94 overload resolution succeeds. The selected overload is then either\n
      \n
    1. OK \xe2\x80\x94 the overall call is well-formed.
    2. \n
    3. not OK (= deleted, protected/private or, perhaps, something else) \xe2\x80\x94 the overall call is ill-formed.
    4. \n
    \n
  4. \n
  5. There are more than one best viable functions \xe2\x80\x94 overload resolution fails with ambiguity.
  6. \n
\n

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?

\n

(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.)

\n
\n

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

\n
/// Would `c(a...)` result in exactly one best viable candidate?\n/// (Where `decltype(c)`, `decltype(a)...` are `C`, `A...`, respectively.)\ntemplate<class C, typename... A>\ninline constexpr bool has_exactly_one_best_viable_call_candidate;\n
Run Code Online (Sandbox Code Playgroud)\n

so the following asserts hold?

\n
struct WithNoViable {\n    void operator ()(void *);\n};\n\nstruct WithDeleted {\n    void operator ()(long) = delete;\n};\n\nstruct WithAmbiguity {\n    void operator ()(long);\n    void operator ()(long long);\n};\n\nstatic_assert(!has_exactly_one_best_viable_call_candidate<WithNoViable, int>);\nstatic_assert( has_exactly_one_best_viable_call_candidate<WithDeleted, int>);\nstatic_assert(!has_exactly_one_best_viable_call_candidate<WithAmbiguity, int>);\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n