Bug 41933 - [c++0x] lambdas and variadic templates don't work together
Summary: [c++0x] lambdas and variadic templates don't work together
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: 4.9.0
Assignee: Jason Merrill
URL:
Keywords: c++-lambda
: 41934 51979 (view as bug list)
Depends on:
Blocks: lambdas
  Show dependency treegraph
 
Reported: 2009-11-04 02:29 UTC by Michael Bruck
Modified: 2022-03-11 00:32 UTC (History)
6 users (show)

See Also:
Host: i686-pc-cygwin
Target: arm-unknown-elf
Build:
Known to work:
Known to fail:
Last reconfirmed: 2009-11-04 03:31:52


Attachments
delegate implementation using a lambda. This doesn't compile. (803 bytes, text/x-c++src)
2012-03-25 05:47 UTC, Jeremy W
Details
delegate implementation not using a lambda. This does compile. (799 bytes, text/x-c++src)
2012-03-25 05:48 UTC, Jeremy W
Details
incomplete patch (1.19 KB, patch)
2012-04-16 19:21 UTC, Jason Merrill
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Bruck 2009-11-04 02:29:28 UTC
$ cat test.c
template <typename... TT>
struct foo
{
    void bar(int i, TT... tt)
    {
        auto l = [tt...](){};
    }
};

void moo()
{
    foo<>       foo;

    foo.bar(0);
}

$ arm-elf-g++.exe -std=gnu++0x -c test.c
test.c: In member function 'void foo<TT>::bar(int, TT ...)':
test.c:6:12: error: parameter packs not expanded with '...':
test.c:6:12: note:         'tt'
test.c:6:14: error: expected ',' before '...' token
test.c:6:14: error: expected identifier before '...' token
test.c: In member function 'void foo<TT>::bar(int, TT ...) [with TT = {}]':
test.c:14:14:   instantiated from here
test.c:6:21: error: using invalid field 'foo<TT>::bar(int, TT ...)::<lambda()>::__tt'
cc1plus: internal compiler error: tree check: expected field_decl, have error_mark in build_lambda_object, at cp/semantics.c:5353
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.

This is with svn rev 153796.
Comment 1 Paolo Carlini 2009-11-04 02:42:06 UTC
A new one... (thanks)
Comment 2 Michael Bruck 2009-11-04 03:15:00 UTC
I filed Bug 41934, which may have related causes.
Comment 3 Jason Merrill 2009-11-04 03:31:52 UTC
Yeah, the hole in the standard is just now being patched:

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#904
Comment 4 Jason Merrill 2009-11-04 15:40:31 UTC
*** Bug 41934 has been marked as a duplicate of this bug. ***
Comment 5 Paolo Carlini 2012-01-24 11:56:18 UTC
*** Bug 51979 has been marked as a duplicate of this bug. ***
Comment 6 Jeremy W 2012-03-25 05:47:37 UTC
Created attachment 26977 [details]
delegate implementation using a lambda. This doesn't compile.
Comment 7 Jeremy W 2012-03-25 05:48:29 UTC
Created attachment 26978 [details]
delegate implementation not using a lambda. This does compile.
Comment 8 Jason Merrill 2012-04-16 19:21:13 UTC
Created attachment 27172 [details]
incomplete patch

Here's the beginning of work to implement this.  A lot more will be needed.
Comment 9 Akim Demaille 2013-05-21 07:15:14 UTC
Hi all,

For what it's worth, Wikipedia has a note about this G++ bug: http://en.wikipedia.org/wiki/Variadic_template .  Below, a test case that passes with clang, but fails to compile with G++ 4.9.


#include <iostream>

struct pass
{
  template<typename ...T> pass(T...) {}
};

template <typename... T>
void print(T... args)
{
   pass{([&]{ std::cout << args << std::endl; }(), 1)...};
}
 
int main()
{
  print(1, "2", 3.4, '5');
}


$ g++-mp-4.9 -Wall var.cc -std=c++11
var.cc: In function 'void print(T ...)':
var.cc:11:54: error: expansion pattern '(<lambda>(), 1)' contains no argument packs
    pass{([&]{ std::cout << args << std::endl; }(), 1)...};
                                                      ^
var.cc: In instantiation of 'void print(T ...) [with T = {int, const char*, double, char}]':
var.cc:16:25:   required from here
var.cc:11:4: error: no matching function for call to 'pass::pass(<brace-enclosed initializer list>)'
    pass{([&]{ std::cout << args << std::endl; }(), 1)...};
    ^
var.cc:11:4: note: candidates are:
var.cc:5:27: note: template<class ... T> pass::pass(T ...)
   template<typename ...T> pass(T...) {}
                           ^
var.cc:5:27: note:   template argument deduction/substitution failed:
var.cc:3:8: note: constexpr pass::pass(const pass&)
 struct pass
        ^
var.cc:3:8: note:   no known conversion for argument 1 from '<type error>' to 'const pass&'
var.cc:3:8: note: constexpr pass::pass(pass&&)
var.cc:3:8: note:   no known conversion for argument 1 from '<type error>' to 'pass&&'
Comment 10 Jason Merrill 2013-09-15 19:34:37 UTC
Author: jason
Date: Sun Sep 15 19:34:34 2013
New Revision: 202604

URL: http://gcc.gnu.org/viewcvs?rev=202604&root=gcc&view=rev
Log:
	PR c++/41933
	* cp-tree.h (DECL_PACK_P): Replace FUNCTION_PARAMETER_PACK_P.
	* cxx-pretty-print.c (direct_declarator): Adjust.
	* decl2.c (cp_build_parm_decl): Adjust.
	* pt.c (function_parameter_pack_p): Adjust.
	(find_parameter_packs_r, push_template_decl_real): Adjust.
	(tsubst_pack_expansion, tsubst_decl): Adjust.
	(regenerate_decl_from_template, instantiate_decl): Adjust.

Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/cp-tree.h
    trunk/gcc/cp/cxx-pretty-print.c
    trunk/gcc/cp/decl2.c
    trunk/gcc/cp/pt.c
Comment 11 Jason Merrill 2013-09-15 19:34:45 UTC
Author: jason
Date: Sun Sep 15 19:34:42 2013
New Revision: 202605

URL: http://gcc.gnu.org/viewcvs?rev=202605&root=gcc&view=rev
Log:
	Core DR 904
	PR c++/41933
	* parser.c (cp_parser_lambda_introducer): Handle variadic capture.
	* lambda.c (add_capture): Handle variadic capture.
	(add_default_capture, lambda_capture_field_type): Likewise.
	(build_capture_proxy, register_capture_members): Likewise.
	* pt.c (register_specialization): Allow FIELD_DECL.
	(retrieve_specialization): Likewise.
	(find_parameter_packs_r): Handle FIELD_DECL and VAR_DECL.
	(tsubst_pack_expansion): Handle FIELD_DECL packs.
	(gen_elem_of_pack_expansion_instantiation): Likewise.
	(instantiate_class_template_1): Likewise.
	(tsubst_decl, tsubst_copy): Likewise.
	(tsubst_expr) [DECL_EXPR]: Handle capture proxy packs.
	(tsubst_copy_and_build) [VAR_DECL]: Likewise.
	* semantics.c (finish_non_static_data_member): Don't try to represent
	the type of a COMPOUND_REF of a FIELD_DECL pack.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic2.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/lambda.c
    trunk/gcc/cp/parser.c
    trunk/gcc/cp/pt.c
    trunk/gcc/cp/semantics.c
Comment 12 Jason Merrill 2013-09-15 19:56:41 UTC
The patches just checked in fix all the testcases that want to capture the entire pack, but not the testcase in comment #9, which wants several different lambdas each capturing an element of the pack.
Comment 13 Paolo Carlini 2013-09-16 09:44:09 UTC
Thanks Jason. I'm having a quick look: is PR47226 actually the same as comment #9 here? In that case we could probably keep only one.
Comment 14 Jason Merrill 2013-09-16 16:37:31 UTC
Yes, thanks for finding the existing PR for that case.