C++14 template code working in GCC 5.1 stops working in 5.2 and 5.3

Yongwei Wu wuyongwei@gmail.com
Sun Jan 10 14:55:00 GMT 2016


Hi GCC gurus,

I have an implementation of Y Combinator in C++, which works in GCC
4.9 to 5.1 as well as Clang 3.5 (in C++14 mode). It stops working in
GCC 5.2 and 5.3. I cannot really whether it is a GCC bug or not, but
it looks like GCC is being too eager in template instantiation. Would
you please check?

--- The code begins ---
#include <functional>
#include <iostream>

// Struct to wrap a function for self-reference.
template <typename _Fn>
struct self_ref_func
{
    std::function<_Fn(self_ref_func)> fn;
};

/**
 * Generates the fixed point using the simple fixed-point combinator.
 * This function takes a curried function of one parameter.
 *
 * @param f  the second-order function to combine with
 * @return   the fixed point
 */
template <typename _Rs, typename _Tp>
std::function<_Rs(_Tp)> fix_simple(
    std::function<std::function<_Rs(_Tp)>(std::function<_Rs(_Tp)>)> f)
{   // Y f = f (λx.(Y f) x)
    return f([f](_Tp&& x)
             {
                 return fix_simple(f)(std::forward<_Tp>(x));
             });
}

/**
 * Generates the fixed point using the Curry-style fixed-point combinator.
 * This function takes a curried function of one parameter.
 *
 * @param f  the second-order function to combine with
 * @return   the fixed point
 */
template <typename _Rs, typename _Tp>
std::function<_Rs(_Tp)> fix_curry(
    std::function<std::function<_Rs(_Tp)>(std::function<_Rs(_Tp)>)> f)
{   // Y = λf.(λx.x x) (λx.f (λy.(x x) y))
    typedef std::function<_Rs(_Tp)>    fn_1st_ord;
    typedef self_ref_func<fn_1st_ord>  fn_self_ref;

    fn_self_ref r = {
        [f](fn_self_ref x)
        {   // λx.f (λy.(x x) y)
            return f(fn_1st_ord([x](_Tp&& y)
                                {
                                    return x.fn(x)(std::forward<_Tp>(y));
                                }));
        }
    };
    return r.fn(r);
}

int main()
{
    using std::function;
    typedef function<int(int)> Func;
    typedef function<Func(Func)> FuncFunc;

    FuncFunc almost_fac = [](Func f)
    {
        return Func([f](int n) {
            if (n <= 1) return 1;
            return n * f(n - 1);
        });
    };

    auto const fac1 = fix_simple(almost_fac);
    auto const fac2 = fix_curry(almost_fac);
    std::cout << fac1(5) << std::endl;
    std::cout << fac2(5) << std::endl;
}
--- The code ends ---

--- The error message begins ---
In file included from test_gcc.cpp:1:0:
/opt/local/include/gcc5/c++/functional: In substitution of
'template<class _Functor, class> std::function<_Res(_ArgTypes
...)>::function(_Functor) [with _Functor =
std::function<std::function<int(int)>(self_ref_func<std::function<int(int)>
>)>; <template-parameter-1-2> = <missing>]':
/opt/local/include/gcc5/c++/functional:1981:45:   recursively required
by substitution of 'template<class _Functor, class>
std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor
= std::function<std::function<int(int)>(self_ref_func<std::function<int(int)>
>)>; <template-parameter-1-2> = <missing>]'
/opt/local/include/gcc5/c++/functional:1981:45:   required by
substitution of 'template<class _Functor, class>
std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor
= std::function<std::function<int(int)>(self_ref_func<std::function<int(int)>
>)>; <template-parameter-1-2> = <missing>]'
test_gcc.cpp:47:51:   required from
'fix_curry(std::function<std::function<_Rs(_Tp)>(std::function<_Rs(_Tp)>)>)::<lambda(fn_self_ref)>::<lambda(_Tp&&)>
[with _Rs = int; _Tp = int]'
test_gcc.cpp:45:34:   required from 'struct
fix_curry(std::function<std::function<_Rs(_Tp)>(std::function<_Rs(_Tp)>)>)::<lambda(fn_self_ref)>
[with _Rs = int; _Tp = int; fn_self_ref =
self_ref_func<std::function<int(int)> >]::<lambda(int&&)>'
test_gcc.cpp:45:21:   required from
'fix_curry(std::function<std::function<_Rs(_Tp)>(std::function<_Rs(_Tp)>)>)::<lambda(fn_self_ref)>
[with _Rs = int; _Tp = int; fn_self_ref =
self_ref_func<std::function<int(int)> >]'
test_gcc.cpp:43:10:   required from 'struct
fix_curry(std::function<std::function<_Rs(_Tp)>(std::function<_Rs(_Tp)>)>)
[with _Rs = int; _Tp = int]::<lambda(fn_self_ref)>'
test_gcc.cpp:50:5:   required from 'std::function<_Rs(_Tp)>
fix_curry(std::function<std::function<_Rs(_Tp)>(std::function<_Rs(_Tp)>)>)
[with _Rs = int; _Tp = int]'
test_gcc.cpp:69:43:   required from here
/opt/local/include/gcc5/c++/functional:1981:69: fatal error: template
instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to
increase the maximum)
  using _Invoke = decltype(__callable_functor(std::declval<_Functor&>())
                                                                     ^
compilation terminated.
--- The error message ends ---

Thanks for any help and advice.

-- 
Wu Yongwei
URL: http://wyw.dcweb.cn/



More information about the Gcc mailing list