This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Lambda templates and implicit function templates.
- From: Adam Butcher <adam at jessamine dot co dot uk>
- To: Jason Merrill <jason at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org, Gabriel Dos Reis <gdr at integrable-solutions dot net>, Andrew Sutton <andrew dot n dot sutton at gmail dot com>, Adam Butcher <adam at jessamine dot co dot uk>
- Date: Sun, 11 Aug 2013 20:49:30 +0100
- Subject: Lambda templates and implicit function templates.
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