Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Local reference to std::cout captured by lambda without asking for it

Have I lost my mind? Was this always permitted?

#include <iostream>

int main()
{
    auto& os = std::cout;

    auto write = []()
    {
        os << "what\n";
    };

    write();
}

I'm using:

Apple LLVM version 10.0.0 (clang-1000.10.44.4)
Target: x86_64-apple-darwin17.7.0

Though also see on Coliru:

(live demo)

I always thought an empty capture would not capture anything.

Indeed, MSDN says:

An empty capture clause, [ ], indicates that the body of the lambda expression accesses no variables in the enclosing scope.

Further research suggests that this is in fact okay for capturing const things (which I also didn't know, but whatever), but os is not const (no reference is! though it is immutable…).

I came across this when turning on -Wextra and noticing that Clang thought a &os capture (which is present in my real code) was unnecessary. Removing it I was staggered to find the build worked.

like image 954
Lightness Races in Orbit Avatar asked Nov 21 '18 15:11

Lightness Races in Orbit


1 Answers

There's an open clang report that cover the case of implicit capture of references by lambda expressions, this is not limited to std::cout but to references variable that are found to refer to constant expressions.

For more reference, the backing defect report on the CWG is CWG-1472

EDIT:

Based on @Rakete1111 comment, I should have pointed out explicitly that clang is right in accepting the code, which is the result of applying the CWG defect mentioned above. The report was reopened because of diagnosis location not because they were wrong about the acceptance

like image 78
Jans Avatar answered Nov 17 '22 05:11

Jans