VC++ 15 calls the wrong copy constructor for lambda capture?
Asked Answered
B

1

13

Consider the following program:

#include <iostream>
struct X {
  X () = default;
  X (X &) { std::cout << "non-const called" << std::endl; }
  X (X const &) { std::cout << "const called" << std::endl; }
  int i () const { return 7; }
};

auto f () {
  X x;
  auto lambda = [=]() { return x.i(); };
  return lambda;
}

int main()
{
  auto lambda = f();
  std::cout << lambda () << std::endl;
  return 0;
}

With VC++15, I get the output

const called
const called
7

With Clang 3.9, I get

non-const called
7

Which compiler is correct here?

Bronchiectasis answered 3/12, 2016 at 16:57 Comment(6)
This may be of your interest. To be straight I don't think your question is a duplicate :)Huoh
It's worth noting that with optimizations enabled, VC also applies RVO resulting in only one call to X(X const&).Chill
@skypjack: Are you sure lambdas construct a const member? ideone.com/RQ7OjC I think the data members are not necessarily const, only operator () is.Bronchiectasis
@Bronchiectasis Fair enough. I'm correcting the answer too. Good catch.Romanfleuve
@Chill still the call should be to X(X &), right?Romanfleuve
@Romanfleuve As far as I know, right.Chill
R
2

I would say that clang is right.
The most suited constructor is called only once when the lambda captures x and the constructor for the returned value is optimized out.
That's why you obtain only one non-const called.


See here and here for further details about copy-elision and RVO.

Romanfleuve answered 3/12, 2016 at 22:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.