Hi Jason,

I've addressed your review comments and provided support for
conversion to function pointer for generic lambdas.  I've sent the
patches as updates to the previous set.  I'll wait for any further
comments before formalizing them into a cleaner set.

The changes now support the examples given in N3690 ยง5.1.2.{5,6} and
the test program included at the end of this mail.  I think it is
feature-complete.

On 19.07.2013 17:56, Jason Merrill wrote:
> On 07/19/2013 05:00 AM, Adam Butcher wrote:
> >
> > +      push_deferring_access_checks (dk_deferred);
> >
> Why do you need this?
>
I don't think I do.  I had thought that it would be necessary to
handle deferred friendship situations but I don't think that can apply
to generic lambdas.  I've ditched them.

> > +/* Nonzero if the function being declared was made a template due to it's
> >
> "its"
>
I've fixed this and a couple of others in my own comments.  I've also
fixed others I found in the same file (as a separate patch).

> > +  else // extend current template parameter list
> >
> Do we still need to do this, now that we're handling all the
> parameters at the end of the parameter list?
>
I think extending the current parameter list is still needed when
'auto' is found in a parameter declaration of an existing function
template.

E.g.
   template <typename T> void f(T& t, auto& a) { ... }

I think that it is necessary to keep everything consistent as if the
template had been declared in the 'conventional' way.  The template
parameter generated for the generic parameter 'a' effectively makes
'f's template parameter list into '<typename T, typename __Gen0>'.

Cheers,
Adam


Patch summary (4):
  Preserve type qualifiers for implicit template parameters.
  Support implicit conversion of a stateless generic lambda to a
    function pointer.
  Address review comments.
  Grammar "it's" to "its".

 gcc/cp/cp-tree.h |  2 +-
 gcc/cp/decl.c    |  3 ++-
 gcc/cp/lambda.c  | 77 +++++++++++++++++++++++++++++++++++++++++---------------
 gcc/cp/parser.c  |  6 ++---
 gcc/cp/pt.c      | 21 ++++++++++------
 5 files changed, 76 insertions(+), 33 deletions(-)


Test program:


  /* 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
  {
    /* 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; }
  
    /* 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);
  }


-- 
1.8.3

Reply via email to