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

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I haven't fully tested this idea yet, but ...

There are two kinds of function type we need to detect: referenceable
functions, and abominable functions.

A referenceable function type is a non-class type that can be converted from T&
to T* (by function-to-pointer conversion).

An abominable function type is a non-referenceable type that is not cv void.

So:

template<typename T, typename = void>
  struct is_referenceable : false_type { };

template<typename T>
  struct is_referenceable<T, __void_t<T&>> : true_type { };

template<typename T, bool = __is_class(T) || __is_union(T), typename = void>
  struct is_referenceable_function : false_type { };

template<typename T>
  struct is_referenceable_function<T, false,
    __void_t<decltype(static_cast<T*>(std::declval<T&>()))>>
  : true_type { };

template<typename T>
  struct is_abominable_function
  : __not_<__or_<is_referenceable<T>, is_void<T>>>::type
  { };

template<typename T>
  struct is_function
  : __or_<is_referenceable_function<T>, is_abominable_function<T>>
  { };


The current definition of __is_referenceable depends on is_object which depends
on is_function, but I think we can simplify it as shown above, and reverse the
dependency.

Reply via email to