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

            Bug ID: 69005
           Summary: [5/6 Regression] infinite(?) recursion in template
                    instantiations
           Product: gcc
           Version: 5.3.1
            Status: UNCONFIRMED
          Keywords: rejects-valid
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redi at gcc dot gnu.org
  Target Milestone: ---

Reduced from https://bugzilla.redhat.com/show_bug.cgi?id=1293086

This used to compile with 5.1 and earlier. Needs C++11 or later.

namespace std
{
  struct true_type { static constexpr bool value = true; };
  struct false_type { static constexpr bool value = false; };

  template<bool Cond, typename T = void> struct enable_if { using type = T; };
  template<> struct enable_if<false> { };

  template<typename T, typename U> struct is_same : false_type { };
  template<typename T> struct is_same<T, T> : true_type { };

  template<bool C, typename If, typename Else>
    struct conditional
    {
      using type = If;
    };

  template<typename If, typename Else>
    struct conditional<false, If, Else>
    {
      using type = Else;
    };

  template<typename If, typename Else>
    struct __and_
    : conditional<If::value, Else, If>::type
    { };

  template<typename If, typename Else>
    struct __or_
    : conditional<If::value, If, Else>::type
    { };

  template<typename T>
    struct __not_
    : conditional<T::value, false_type, true_type>::type
    { };

  template<typename T>
    T declval();
}

  template<typename _Sig> class function;

  template<typename _Res, typename _Arg>
    class function<_Res(_Arg)>
    {
      typedef _Res _Signature_type(_Arg);

      template<typename _Functor>
        using _Invoke
        = decltype(std::declval<_Functor&>()(std::declval<_Arg>()));

      // Used so the return type convertibility checks aren't done when
      // performing overload resolution for copy construction/assignment.
      template<typename _Tp>
        using _NotSelf = std::__not_<std::is_same<_Tp, function>>;

      template<typename _Functor>
        using _Callable
          = std::__and_<_NotSelf<_Functor>,
                   std::is_same<_Invoke<_Functor>, _Res>>;

      template<typename _Cond, typename _Tp>
        using _Requires = typename std::enable_if<_Cond::value, _Tp>::type;

    public:
      function() noexcept { }

      function(const function&) { }

      template<typename _Functor,
               typename = _Requires<_Callable<_Functor>, void>>
        function(_Functor) { }

      _Res operator()(_Arg) const;
    };

struct Foo {
  using Func = function<void(Foo)>;

  static const Func DefaultFunc;

  Func CurrentFunc = DefaultFunc;
};

Reply via email to