https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102065

Patrick Palka <ppalka at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |DUPLICATE
                 CC|                            |ppalka at gcc dot gnu.org
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #1 from Patrick Palka <ppalka at gcc dot gnu.org> ---
Thanks for the bug report!  Looks like this apparent regression started with
r11-2774 (which implements the changes in wg21.link/cwg2369).

But I think GCC's behavior is correct here, according to the latest standard. 
The associated constraints of a function template are checked immediately after
deducing all template arguments, rather than after substituting the deduced
template arguments into the function type, so your use of enable_if_t as a
function parameter doesn't actually prevent the std::invocable constraint from
getting checked (and for the hard error to occur when this constraint check
causes the body of the lambda to get instantiated with int*).

One work around in your case is to give the lambda a non-deduced return type of
'void' so that we don't need to instantiate the body of the lambda during the
std::invocable check:

        [](auto e) -> void
        {
            elem_func(e);
        }

Another more general workaround is to instead encode the enable_if_t test as an
additional constraint that guards the std::invocable constraint, something
like:

#include <functional>

void elem_func(int) {}

template <
    typename Sequence,
    typename SequenceHandler
>
  requires std::is_pointer_v<Sequence> && std::invocable<SequenceHandler, int>
void func(
    const Sequence& values,
    SequenceHandler&& handler)
{
}

template <
    typename T,
    typename ValueHandler
>
  requires (!std::is_pointer_v<T>) && std::invocable<ValueHandler, T>
void func(
    T value,
    ValueHandler&& handler)
{
}

int main()
{
    func(
        new int[1], // pointer => 1st func should be called 
        [](auto e)  // lambda should be std::invocable<int> => decltype(e)==int
        {
            elem_func(e); // cannot call elem_func if decltype(e)==int* (2nd
func)
        }
    );
}

*** This bug has been marked as a duplicate of bug 99599 ***

Reply via email to