18
#include <cassert>
#include <cmath>

int main()
{
    struct point_of_cone
    {
        double x, y;
        double z = [&] { using std::sqrt; return sqrt(x * x + y * y); }();
    };
    point_of_cone p = {3.0, 4.0};
    assert(p.z == 5.0);
}

Works fine for clang++ from trunk, but for g++ from trunk fails with error message (link):

error: 'this' was not captured for this lambda function

Definition of point_of_cone in namespace scope works fine for both.

Slightly modified definition with [this] lambda capture works fine also for both in either global or local scope.

Which compiler is right?

Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
  • post that code in your question, please – xaxxon Oct 18 '16 at 11:07
  • @Orient No, I was referring to xaxxon's godbolt link, where he set the wrong flag. – Columbo Oct 18 '16 at 11:11
  • Hmm the question is should `[&]` capture `this`. Not sure about new standards but the answer here suggest not: http://stackoverflow.com/questions/16323032/why-cant-i-capture-this-by-reference-this-in-lambda – Hayt Oct 18 '16 at 11:16
  • @Hayt &this is different. – xaxxon Oct 18 '16 at 11:21
  • @xaxxon where is `[&this]` meantioned? I meant if the default capture `[&]` would include `this` or not. – Hayt Oct 18 '16 at 11:27
  • 1
    @Hayt "If a lambda-capture includes a capture-default that is &, no identifier in a simple-capture of that lambda-capture shall be preceded by &. If a lambda-capture includes a capture-default that is =, each simple-capture of that lambda-capture shall be of the form “& identifier” or “* this”. **[ Note: The form [&,this] is redundant but accepted for compatibility with ISO C++ 2014. — end note ]**" I don't completely understand that whole section, but the comment makes it clear that [&] captures this – xaxxon Oct 18 '16 at 11:33
  • Yeah I was not sure about this too, but this seems to indicate [&] should capture this. – Hayt Oct 18 '16 at 11:37
  • @orient why did you delete the comment with the actual source code that reproduces the error without editing your question to include it? – xaxxon Oct 18 '16 at 11:39
  • @xaxxon The link was placed in the main question text, as you suggested. – Tomilov Anatoliy Oct 18 '16 at 11:40
  • @xaxxon Is it better to post whole code from the link? – Tomilov Anatoliy Oct 18 '16 at 11:42
  • 1
    @Orient your question should have all the code necessary to reproduce your question – xaxxon Oct 18 '16 at 11:43
  • @xaxxon It is done. – Tomilov Anatoliy Oct 18 '16 at 11:44
  • @Orient thank you :) This helps other people that have a problem know if they have the same problem or not more quickly. And the question is still good even if the question link dies for some reason. – xaxxon Oct 18 '16 at 11:44
  • (The operator in the assert is dangerous - 4.0 can be represented exactly…) – greybeard Nov 11 '16 at 00:11
  • @greybeard 3.0, 4.0 and 5.0 has exact representation. There is no problem. Comparison with tolerance can complicate example. – Tomilov Anatoliy Nov 11 '16 at 01:41
  • `There is no problem` as in 9.0, 16.0, 25.0 have exact representations, and the result of std::sqrt(25.0) is _guaranteed_ to be exact? I would need to read up on C++, if&when necessity arises. – greybeard Nov 11 '16 at 01:50
  • @greybeard I think it is about IEEE 754. – Tomilov Anatoliy Nov 11 '16 at 02:04
  • That would indeed require it to be exact - used to be the only function in addition to the operators such constrained, seems to have been joined by _fused multiply-add_ since. (And might suggest using `hypot()`.) – greybeard Nov 11 '16 at 02:10
  • @greybeard What do you think? Should I change `double` to `int` to make example better? – Tomilov Anatoliy Nov 11 '16 at 03:04
  • (from an off-handed remark to such trickiness) `Should I change double to int to make example better?` Or even pick a different example altogether that doesn't try to compare results of transcendental functions for equality, seeing the example is to illustrate capturing in a lambda, and the length of this exchange about [comparing doubles for equality](http://stackoverflow.com/a/77735/3789665). On a side note: `hypot()` avoids `undue overflow or underflow at intermediate stages`, but I can't seem to find an exactness required equivalent to `sqrt()`. – greybeard Nov 11 '16 at 03:50

1 Answers1

11

That's a gcc bug.

int main() {
    struct A {
        int x, i = [&] { return x; }();
    } a{0};
}

This fails, but if we…

  • change & to this, or
  • declare A as having namespace scope,

it works. Neither of these should have any effect on the well-formedness, though.

Reported: #78019.

Vaughn Cato
  • 63,448
  • 5
  • 82
  • 132
Columbo
  • 60,038
  • 8
  • 155
  • 203
  • If this is the same bug I've wandered into several times recently, then another workaround for it is to explicitly say `this->`. – Griwes Oct 18 '16 at 16:31
  • 2
    @Griwes Could you have used the contrapositive to deduce that this isn't the bug you've wandered into? :-) – Columbo Oct 18 '16 at 18:18