Hi Jason, I decided to go ahead and submit the latest cleaned up version of the generic lambda and implicit function template patches. I think all review comments have been addressed. As well as the cleanup there are a few enhancements; generic lambda instantiations in diagnostics now show template argument bindings and the appropriate -std=xxx guards have been put in place. I've also fixed a couple of cases where invalid user code caused an ICE.
I am yet to write some tests for individual features to be included in the source tree but intend to when I get some more time. In the meantime I've included the two main tests I've used for trials. Cheers, Adam -------------------------------- Patch summary (3): Support lambda templates. Support using 'auto' in a function parameter list to introduce an implicit template parameter. Support dumping type bindings in lambda diagnostics. gcc/cp/cp-tree.h | 11 ++++ gcc/cp/decl.c | 19 +++++- gcc/cp/decl2.c | 5 +- gcc/cp/error.c | 22 +++---- gcc/cp/lambda.c | 87 +++++++++++++++++++------ gcc/cp/parser.c | 98 +++++++++++++++++++++++++--- gcc/cp/pt.c | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 7 files changed, 375 insertions(+), 60 deletions(-) -------------------------------- Basic compile and runtime check: /* Implicit function templates at namespace scope. */ auto f1 (auto& a, auto const& b) { return a += b; } template <typename A> auto f2 (A& a, auto const& b) { return a += b; } template <typename B> auto f3 (auto& a, B const& b) { return a += b; } template <typename A, typename B> auto f4 (A& a, B const& b) { return a += b; } struct S { /* Implicit non-static member function templates. */ auto mf1 (auto& a, auto const& b) { return a += b; } template <typename A> auto mf2 (A& a, auto const& b) { return a += b; } template <typename B> auto mf3 (auto& a, B const& b) { return a += b; } template <typename A, typename B> auto mf4 (A& a, B const& b) { return a += b; } /* Implicit static member function templates. */ static auto smf1 (auto& a, auto const& b) { return a += b; } template <typename A> static auto smf2 (A& a, auto const& b) { return a += b; } template <typename B> static auto smf3 (auto& a, B const& b) { return a += b; } template <typename A, typename B> static auto smf4 (A& a, B const& b) { return a += b; } }; #undef NDEBUG #include <cassert> #define CHECK(A, b, f) do { \ A a1 = 5, a2 = 12; \ auto r1 = f (a1, b); \ auto r2 = f (a2, b); \ assert ((#f, a1 == 5 + b)); \ assert ((#f, a2 == 12 + b)); \ assert ((#f, r1 == a1)); \ assert ((#f, r2 == a2)); \ } while (0) #define INVOKEi(f, A, b, i) do { CHECK (A, b, f ## i); } while (0) #define INVOKE4(f, A, b) do { INVOKEi (f, A, b, 1); \ INVOKEi (f, A, b, 2); \ INVOKEi (f, A, b, 3); \ INVOKEi (f, A, b, 4); } while (0) #define AS_FUNi(f, A, b, i) do { CHECK (A, b, f ## i._FUN); } while (0) #define AS_FUN4(f, A, b) do { AS_FUNi (f, A, b, 1); \ AS_FUNi (f, A, b, 2); \ AS_FUNi (f, A, b, 3); \ AS_FUNi (f, A, b, 4); } while (0) #define AS_PTRi(f, A, B, b, i) do { A (*pfn) (A&, B const&) = f ## i; \ CHECK (A, b, pfn); } while (0) #define AS_PTR4(f, A, B, b) do { AS_PTRi (f, A, B, b, 1); \ AS_PTRi (f, A, B, b, 2); \ AS_PTRi (f, A, B, b, 3); \ AS_PTRi (f, A, B, b, 4); } while (0) int main() { /* Check namespace templates. */ INVOKE4 (f, float, 7); AS_PTR4 (f, float, int, 7); /* Check member templates. */ S s; INVOKE4 (s.mf, float, 7); INVOKE4 (s.smf, float, 7); INVOKE4 (S::smf, float, 7); AS_PTR4 (s.smf, float, int, 7); AS_PTR4 (S::smf, float, int, 7); /* Regression check non-template stateless lambda and its conversion to function pointer. */ auto lf0 = [] (float& a, int const& b) { return a += b; }; INVOKEi (lf, float, 7, 0); AS_FUNi (lf, float, 7, 0); AS_PTRi (lf, float, int, 7, 0); /* Check stateless lambda templates. */ auto lf1 = [] (auto& a, auto const& b) { return a += b; }; auto lf2 = [] <typename A> (A& a, auto const& b) { return a += b; }; auto lf3 = [] <typename B> (auto& a, B const& b) { return a += b; }; auto lf4 = [] <typename A, typename B> (A& a, B const& b) { return a += b; }; INVOKE4 (lf, float, 7); AS_FUN4 (lf, float, 7); AS_PTR4 (lf, float, int, 7); /* Check capturing lambda templates. */ int i; auto lc1 = [i] (auto& a, auto const& b) { return a += b; }; auto lc2 = [i] <typename A> (A& a, auto const& b) { return a += b; }; auto lc3 = [i] <typename B> (auto& a, B const& b) { return a += b; }; auto lc4 = [i] <typename A, typename B> (A& a, B const& b) { return a += b; }; INVOKE4 (lc, float, 7); } -------------------------------- Dependent type check: struct S { struct N { float test () {} }; }; int main() { auto f = [] <typename T> (T const& s) { typename T::N x; return x.test (); }; auto g = [] (auto const& s) { typename std::decay<decltype (s)>::type::N x; return x.test (); }; S i; f(i); g(i); float (*pfn) (S const&) = f; pfn(i); pfn = g; return pfn(i); } -- 1.8.3