13

Strangely enough, GCC 4.7.2 seems to have no problem with the following code:

template<typename T>
T&& identity(T&& x1) {
    return std::forward<T>(x1);
}

int main(int, char**) {
    int x1 = 1;
    int &x2 = identity(x1);
    auto f = [&x1]() mutable {
        x1 = x1 + 1;
    };
    auto g1 = [y=x2+1]() {
        static_assert(std::is_same<decltype(y), const int>::value, "fail");
        std::cout << "g1: " << y << std::endl;
    };
    auto h1 = [y=identity(x1)+1]() {
        static_assert(std::is_same<decltype(y), const int>::value, "fail");
        std::cout << "h1: " << y << std::endl;
    };
    auto g2 = [&y=x2]() {
        static_assert(std::is_same<decltype(y), int&>::value, "fail");
        std::cout << "g2: " << y << std::endl;
    };
    auto h2 = [&y=identity(x1)]() {
        static_assert(std::is_same<decltype(y), int&>::value, "fail");
        std::cout << "h2: " << y << std::endl;
    };
    f(); g1(); h1(); g2(); h2();
    f(); g1(); h1(); g2(); h2();
    return 0;
}

The results are the following:

g1: 2
h1: 2
g2: 2
h2: 2
g1: 2
h1: 2
g2: 3
h2: 3

I can't seem to find any mention of capturing arbitrary expressions in lambda capture lists, even in n3285 (dated 2012-10-02). Also, I can't seem to find any documentation of this as an official GCC extension anywhere.

Is this an undocumented GCC extension (a la VLAs as structure members, a proposed/upcoming C++ feature that GCC has gone ahead and implemented early, neither, both, or what?

Community
  • 1
  • 1
Stephen Lin
  • 5,470
  • 26
  • 48
  • 1
    There is a [proposal](http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3610.html) for something like this. – John Schug Apr 02 '13 at 03:58
  • @JohnSchug oh, but that's dated 2013-03-15! So the answer is "both"? (since this seems to predate the proposal?) – Stephen Lin Apr 02 '13 at 04:08
  • (It also doesn't seem to mention the GCC implementation, so it might be developed completely independently of this.) – Stephen Lin Apr 02 '13 at 04:13
  • 9
    After searching through the gcc source code for the past 10 minutes, I have found the [portion](http://gcc.gnu.org/viewcvs/gcc/tags/gcc_4_7_2_release/gcc/cp/parser.c?view=markup) that deals with this in lines 8239-8250. It seems to have been introduced by revision 139245 to branch cxx0x-lambdas-branch which was created back in 2008. – John Schug Apr 02 '13 at 05:01
  • @JohnSchug wow, thanks...I guess it's been there forever then. If you want to write up your finding in an answer I'll accept it, pending some insider with first-hand knowledge coming up with something more detailed. – Stephen Lin Apr 02 '13 at 05:50

1 Answers1

5

As noted in the comments, the feature is broadly similar to a recent proposal but it was implemented long before initial standardization. GCC served as a prototype during the standard development and initially reflected whatever ideas the authors liked, which were later refined. Some ideas which had to be trimmed to keep the standard reasonably simple are getting reintroduced as proposals. Lambdas have a lot of room to grow.

For now, this is just another bug. It was never removed from the original implementation because nobody has reported it yet.


Update: This is now a standard feature since C++14.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421