Date: Sat, 29 Oct 2022 19:29:41 -0700
In [func.require], we have the definition of INVOKE(f, t1, t2, ..., tN),
which has a number of cases. The first two are
(t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class
T and is_base_of_v<T, remove_reference_t<decltype(t1)>> is true;
and
(t1.get().*f)(t2, ..., tN) when f is a pointer to a member function of a
class T and remove_cvref_t<decltype(t1)> is a specialization of
reference_wrapper;
There is no mention of which of these is to be preferred if the
conditions hold in both cases.
So, given
using refwrap = std::reference_wrapper<int>;
is std::is_invocable_v<void (refwrap::*)(), refwrap> true? If the first
case takes precedence, then yes. If the second case, then no.
A quick check on Godbolt shows that GCC and Clang evaluate the previous
expression to false, while MSVC evaluates it to true.
A similar ambiguity exists for the pointer-to-data-member case.
(I had originally written the following example, which yields a compiler
error on GCC and Clang, but is accepted by MSVC. But then I realized
that it violates the general ban on creating pointers to library functions.)
void f(std::reference_wrapper<int> x)
{
std::invoke(&std::reference_wrapper<int>::get, x);
}
which has a number of cases. The first two are
(t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class
T and is_base_of_v<T, remove_reference_t<decltype(t1)>> is true;
and
(t1.get().*f)(t2, ..., tN) when f is a pointer to a member function of a
class T and remove_cvref_t<decltype(t1)> is a specialization of
reference_wrapper;
There is no mention of which of these is to be preferred if the
conditions hold in both cases.
So, given
using refwrap = std::reference_wrapper<int>;
is std::is_invocable_v<void (refwrap::*)(), refwrap> true? If the first
case takes precedence, then yes. If the second case, then no.
A quick check on Godbolt shows that GCC and Clang evaluate the previous
expression to false, while MSVC evaluates it to true.
A similar ambiguity exists for the pointer-to-data-member case.
(I had originally written the following example, which yields a compiler
error on GCC and Clang, but is accepted by MSVC. But then I realized
that it violates the general ban on creating pointers to library functions.)
void f(std::reference_wrapper<int> x)
{
std::invoke(&std::reference_wrapper<int>::get, x);
}
Received on 2022-10-30 02:29:52