1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AUTOSAR CountdownAdvent Calendar 2022

Day 10

C++ N4606 (37)5.1.5 Lambda expressions [expr.prim.lambda] p97

Last updated at Posted at 2018-04-17

はじめに

N4606 Working Draft, Standard for Programming Language C++
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/#mailing2016-11
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf

n4606は、ISO/IEC JTC1 SC22 WG21の作業原案(Working Draft)です。
公式のISO/IEC 14882原本ではありません。
ISO/IEC JTC1 SC22 WG21では、可能な限り作業文書を公開し、幅広い意見を求めています。
一連の記事はコード断片をコンパイルできる形にする方法を検討してコンパイル、リンク、実行して、規格案の原文と処理系(g++, Clang++)との違いを確認し、技術内容を検討し、ISO/IEC JTC1 SC22 WG21にフィードバックするために用います。
また、CERT C++, MISRA C++等のコーディング標準のコード断片をコンパイルする際の参考にさせていただこうと考えています。CERT C++, MISRA C++が標準化の動きとの時間的なずれがあれば確認できれば幸いです。また、boostライブラリとの関連、Linux OS, TOPPERSカーネル、g++(GCC), clang++(LLVM)との関係も調査中です。
何か、抜け漏れ、耳より情報がありましたらおしらせくださると幸いです。

作業方針

1)コンパイルエラーを収集する。
2)コンパイルエラーをなくす方法を検討する。
コンパイルエラーになる例を示すだけが目的のコードは、コンパイルエラーをなくすのではなく、コンパイルエラーの種類を収集するだけにする。
文法を示すのが目的のコード場合に、コンパイルエラーをなくすのに手間がかかる場合は、順次作業します。
3)リンクエラーをなくす方法を検討する。
文法を示すのが目的のコード場合に、リンクエラーをなくすのに手間がかかる場合は、順次作業します。
4)意味のある出力を作る。
コンパイル、リンクが通っても、意味のある出力を示そうとすると、コンパイル・リンクエラーが出て収拾できそうにない場合がある。順次作業します。

1)だけのものから4)まで進んだものと色々ある状態です。一歩でも前に進むご助言をお待ちしています。「検討事項」の欄に現状を記録するようにしています。

list

N4606 Working Draft 2016, ISO/IEC 14882, C++ standard(1) coding list
https://qiita.com/kaizen_nagoya/items/df5d62c35bd6ed1c3d43/

Compiler

clang++ --version

clang version 6.0.0 (tags/RELEASE_600/final)

g++-7 --version

g++-7 (Homebrew GCC 7.3.0_1) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.
#(37)5.1.5 Lambda expressions [expr.prim.lambda]
p97

p97.cpp
// N4606 Committee Draft, Standard for Programming Language C++
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf 
#define msg "p97.cpp (37)5.1.5 Lambda expressions [expr.prim.lambda]"

#include <iostream>
#include <cassert>
#include <algorithm>
#include <cmath>
#include <utility> 
#include <type_traits>

void abssort(float* x, unsigned N) {
std::sort(x, x + N,
[](float a, float b) {
return std::abs(a) < std::abs(b);
});
}

auto monoid = [](auto v) { return [=] { return v; }; };
auto add = [](auto m1) constexpr {
auto ret = m1();
return [=](auto m2) mutable {
auto m1val = m1();
auto plus = [=](auto m2val) mutable constexpr
{ return m1val += m2val; };
ret = plus(m2());
return monoid(ret);
};
};
constexpr auto zero = monoid(0);
constexpr auto one = monoid(1);
static_assert(add(one)(zero)() == one()); // OK
// Since two below is not declared constexpr, an evaluation of its constexpr member function call operator
// cannot perform an lvalue-to-rvalue conversion on one of its subobjects (that represents its capture)
// in a constant expression.
auto two = monoid(2);
assert(two() == 2); // OK, not a constant expression.
static_assert(add(one)(one)() == two()); // ill-formed: two() is not a constant expression
static_assert(add(one)(one)() == monoid(2)()); // OK

auto x1 = [](int i){ return i; }; // OK: return type is int
auto x2 = []{ return { 1, 2 }; }; // error: deducing return type from braced-init-list
int j;
auto x3 = []()->auto&& { return j; }; // OK: return type is int&

auto glambda = [](auto a, auto&& b) { return a < b; };
bool b = glambda(3, 3.14); // OK
auto vglambda = [](auto printer) {
return [=](auto&& ... ts) { // OK: ts is a function parameter pack
printer(std::forward<decltype(ts)>(ts)...);
return [=]() {
printer(ts ...);
};
};
};
auto p = vglambda( [](auto v1, auto v2, auto v3)
{ std::cout << v1 << v2 << v3; } );
auto q = p(1, 'a', 3.14); // OK: outputs 1a3.14
q(); // OK: outputs 1a3.14

auto ID = [](auto a) { return a; };
static_assert(ID(3) == 3); // OK
struct NonLiteral {
NonLiteral(int n) : n(n) { }
int n;
};

static_assert(ID(NonLiteral{3}).n == 3); // function template. Consider the following:
auto glambda = [](auto a) { return a; };
int (*fp)(int) = glambda;

struct Closure {
template<class T> auto operator()(T t) const { ... }
template<class T> static auto lambda_call_operator_invoker(T a) {
// forwards execution to operator()(a) and therefore has
// the same return type deduced
...
}
template<class T> using fptr_t =
decltype(lambda_call_operator_invoker(declval<T>())) (*)(T);
template<class T> operator fptr_t<T>() const
{ return &lambda_call_operator_invoker; }
};

void f1(int (*)(int)) { }
void f2(char (*)(int)) { }
void g(int (*)(int)) { } // #1
void g(char (*)(char)) { } // #2
void h(int (*)(int)) { } // #3
void h(char (*)(int)) { } // #4
auto glambda = [](auto a) { return a; };
f1(glambda); // OK
f2(glambda); // error: ID is not convertible
g(glambda); // error: ambiguous
h(glambda); // OK: calls #3 since it is convertible from ID
int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK

auto GL = [](auto a) { std::cout << a; return a; };
int (*GL_int)(int) = GL; // OK: through conversion function template
GL_int(3); // OK: same as GL(3)

auto Fwd = [](int (*fp)(int), auto a) { return fp(a); };
auto C = [](auto a) { return a; };
static_assert(Fwd(C,3) == 3); // OK
// No specialization of the function call operator template can be constexpr (due to the local static).
auto NC = [](auto a) { static int s; return a; };
static_assert(Fwd(NC,3) == 3); // ill-formed

struct S1 {
int x, y;
int operator()(int);
void f() {
[=]()->int {
return operator()(this->x + y); // equivalent to S1::operator()(this->x + (*this).y)
// this has type S1*
};
}
};

struct S2 { void f(int i); };
void S2::f(int i) {
[&, i]{ }; // OK
[&, &i]{ }; // error: i preceded by & when & is the default
[=, *this]{ }; // OK
[=, this]{ }; // error: this when = is the default
[i, i]{ }; // error: i repeated
[this, *this]{ }; // error: this appears twice
}

void f(int, const int (&)[2] = {}) { } // #1
void f(const int&, const int (&)[1]) { } // #2
void test() {
const int x = 17;
auto g = [](auto a) {
f(x); // OK: calls #1, does not capture x
};
auto g2 = [=](auto a) {
int selector[sizeof(a) == 1 ? 1 : 2]{};
f(x, selector); // OK: is a dependent expression, so captures x
};
}

void f1(int i) {
int const N = 20;
auto m1 = [=]{
int const M = 30;
auto m2 = [i]{
int x[N][M]; // OK: N and M are not odr-used
x[0][0] = i; // OK: i is explicitly captured by m2
// and implicitly captured by m1
};
};
struct s1 {
int f;
void work(int n) {
int m = n*n;
int j = 40;
auto m3 = [this,m] {
auto m4 = [&,j] { // error: j not captured by m3
int x = n; // error: n implicitly captured by m4
// but not captured by m3
x += m; // OK: m implicitly captured by m4
// and explicitly captured by m3
x += i; // error: i is outside of the reaching scope
x += f; // OK: this captured implicitly by m4
// and explicitly by m3
};
};
}
};
}
struct


int main(int argc, char *argv[], char *envp[]){
 p p1=argv;
  int i=3;
  q q1 = &i;
  pi pi1 = &q1;
  pci pci1 = &pi1;
  std::cout << "p1="<<p1 <<" q1=" << q1 << " pi1="<<pi1<<" pci1="<<pci1<<std::endl;
  std::cout << msg << std::endl;
  return EXIT_SUCCESS;
}

struct s2 {
double ohseven = .007;
auto f() {
return [this] {
return [*this] {
return ohseven; // OK
}
}();
}
auto g() {
return [] {
return [*this] { }; // error: *this not captured by outer lambda-expression
}();
}
};


void f2() {
int i = 1;
void g1(int = ([i]{ return i; })()); // ill-formed
void g2(int = ([i]{ return 0; })()); // ill-formed
void g3(int = ([=]{ return i; })()); // ill-formed
void g4(int = ([=]{ return 0; })()); // OK
void g5(int = ([]{ return sizeof i; })()); // OK


void f(const int*);
void g() {
const int N = 10;
[=] {
int arr[N]; // OK: not an odr-use, refers to automatic variable
f(&N); // OK: causes N to be captured; &N points to the
// corresponding member of the closure type
};
}


// The inner closure type must be a literal type regardless of how reference captures are represented.
static_assert([](int n) { return [&n] { return ++n; }(); }(3) == 4);

Example: the nested lambda expressions and invocations below will output 123234.
int a = 1, b = 1, c = 1;
auto m1 = [a, &b, &c]() mutable {
auto m2 = [a, b, &c]() mutable {
std::cout << a << b << c;
a = 4; b = 4; c = 4;
};
a = 3; b = 3; c = 3;
m2();
};
a = 2; b = 2; c = 2;
m1();
std::cout << a << b << c;

void f3() {
float x, &r = x;
[=] { // x and r are not captured (appearance in a decltype operand is not an odr-use)
decltype(x) y1; // y1 has type float
decltype((x)) y2 = y1; // y2 has type float const& because this lambda
// is not mutable and x is an lvalue
decltype(r) r1 = y1; // r1 has type float& (transformation not considered)
decltype((r)) r2 = y2; // r2 has type float const&
};
}
template<class... Args>
void f(Args... args) {
auto lm = [&, args...] { return g(args...); };
lm();


}
int main(int argc, char *argv[], char *envp[]){


  std::cout << msg << std::endl;
  return EXIT_SUCCESS;
}
$ ./cppgl17.sh p97
$ clang++ p97.cpp
p97.cpp:37:1: error: expected parameter declarator
assert(two() == 2); // OK, not a constant expression.
^
/usr/include/assert.h:93:23: note: expanded from macro 'assert'
    (__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, #e) : (void)0)
                      ^
p97.cpp:37:1: error: expected ')'
/usr/include/assert.h:93:23: note: expanded from macro 'assert'
    (__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, #e) : (void)0)
                      ^
p97.cpp:37:1: note: to match this '('
/usr/include/assert.h:93:22: note: expanded from macro 'assert'
    (__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, #e) : (void)0)
                     ^
p97.cpp:37:1: error: expected ')'
assert(two() == 2); // OK, not a constant expression.
^
/usr/include/assert.h:93:32: note: expanded from macro 'assert'
    (__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, #e) : (void)0)
                               ^
p97.cpp:37:1: note: to match this '('
/usr/include/assert.h:93:5: note: expanded from macro 'assert'
    (__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, #e) : (void)0)
    ^
p97.cpp:37:1: error: C++ requires a type specifier for all declarations
assert(two() == 2); // OK, not a constant expression.
^
/usr/include/assert.h:93:6: note: expanded from macro 'assert'
    (__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, #e) : (void)0)
     ^
p97.cpp:38:15: error: static_assert expression is not an integral constant expression
static_assert(add(one)(one)() == two()); // ill-formed: two() is not a constant expression
              ^~~~~~~~~~~~~~~~~~~~~~~~
p97.cpp:19:48: note: read of non-constexpr variable 'two' is not allowed in a constant expression
auto monoid = [](auto v) { return [=] { return v; }; };
                                               ^
p97.cpp:38:34: note: in call to '&two->operator()()'
static_assert(add(one)(one)() == two()); // ill-formed: two() is not a constant expression
                                 ^
p97.cpp:36:6: note: declared here
auto two = monoid(2);
     ^
p97.cpp:42:22: error: cannot deduce lambda return type from initializer list
auto x2 = []{ return { 1, 2 }; }; // error: deducing return type from braced-init-list
                     ^~~~~~~~
p97.cpp:59:1: error: C++ requires a type specifier for all declarations
q(); // OK: outputs 1a3.14
^
p97.cpp:68:15: error: static_assert expression is not an integral constant expression
static_assert(ID(NonLiteral{3}).n == 3); // function template. Consider the following:
              ^~~~~~~~~~~~~~~~~~~~~~~~
p97.cpp:68:15: note: non-literal type 'NonLiteral' cannot be used in a constant expression
p97.cpp:69:6: error: redefinition of 'glambda'
auto glambda = [](auto a) { return a; };
     ^
p97.cpp:46:6: note: previous definition is here
auto glambda = [](auto a, auto&& b) { return a < b; };
     ^
p97.cpp:70:7: error: no viable conversion from '(lambda at p97.cpp:46:16)' to 'int (*)(int)'
int (*fp)(int) = glambda;
      ^          ~~~~~~~
p97.cpp:46:16: note: candidate template ignored: failed template argument deduction
auto glambda = [](auto a, auto&& b) { return a < b; };
               ^
p97.cpp:80:39: error: no template named 'declval'; did you mean 'std::declval'?
decltype(lambda_call_operator_invoker(declval<T>())) (*)(T);
                                      ^~~~~~~
                                      std::declval
/usr/local/Cellar/llvm/6.0.0/include/c++/v1/type_traits:1147:1: note: 'std::declval' declared here
declval() _NOEXCEPT;
^
p97.cpp:80:39: error: no template named 'declval'; did you mean 'std::declval'?
decltype(lambda_call_operator_invoker(declval<T>())) (*)(T);
                                      ^~~~~~~
                                      std::declval
/usr/local/Cellar/llvm/6.0.0/include/c++/v1/type_traits:1147:1: note: 'std::declval' declared here
declval() _NOEXCEPT;
^
p97.cpp:73:48: error: expected expression
template<class T> auto operator()(T t) const { ... }
                                               ^
p97.cpp:77:1: error: expected expression
...
^
p97.cpp:91:6: error: redefinition of 'glambda'
auto glambda = [](auto a) { return a; };
     ^
p97.cpp:46:6: note: previous definition is here
auto glambda = [](auto a, auto&& b) { return a < b; };
     ^
p97.cpp:92:1: error: unknown type name 'f1'
f1(glambda); // OK
^
p97.cpp:93:1: error: unknown type name 'f2'
f2(glambda); // error: ID is not convertible
^
p97.cpp:94:1: error: unknown type name 'g'
g(glambda); // error: ambiguous
^
p97.cpp:95:1: error: unknown type name 'h'
h(glambda); // OK: calls #3 since it is convertible from ID
^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.

$ g++-7 p97.cpp
p97.cpp:176:1: error: stray '\343' in program
 ???p p1=argv;
 ^
p97.cpp:176:2: error: stray '\200' in program
 ???p p1=argv;
  ^
p97.cpp:176:3: error: stray '\200' in program
 ??p p1=argv;
   ^
In file included from /usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/cassert:44:0,
                 from p97.cpp:6:
p97.cpp:37:1: error: expected ')' before '(' token
 assert(two() == 2); // OK, not a constant expression.
 ^
p97.cpp:38:1: error: non-constant condition for static assertion
 static_assert(add(one)(one)() == two()); // ill-formed: two() is not a constant expression
 ^~~~~~~~~~~~~
p97.cpp:38:37:   in constexpr expansion of 'two.<lambda(auto:1)> [with auto:1 = int]::<lambda()>()'
p97.cpp:38:1: error: the value of 'two' is not usable in a constant expression
p97.cpp:36:6: note: 'two' was not declared 'constexpr'
 auto two = monoid(2);
      ^~~
p97.cpp: In lambda function:
p97.cpp:42:29: error: returning initializer list
 auto x2 = []{ return { 1, 2 }; }; // error: deducing return type from braced-init-list
                             ^
p97.cpp: At global scope:
p97.cpp:59:4: error: expected constructor, destructor, or type conversion before ';' token
 q(); // OK: outputs 1a3.14
    ^
p97.cpp:68:1: error: non-constant condition for static assertion
 static_assert(ID(NonLiteral{3}).n == 3); // function template. Consider the following:
 ^~~~~~~~~~~~~
p97.cpp:68:17: error: temporary of non-literal type 'NonLiteral' in a constant expression
 static_assert(ID(NonLiteral{3}).n == 3); // function template. Consider the following:
               ~~^~~~~~~~~~~~~~~
p97.cpp:63:8: note: 'NonLiteral' is not literal because:
 struct NonLiteral {
        ^~~~~~~~~~
p97.cpp:63:8: note:   'NonLiteral' is not an aggregate, does not have a trivial default constructor, and has no constexpr constructor that is not a copy or move constructor
p97.cpp:69:6: error: conflicting declaration 'auto glambda'
 auto glambda = [](auto a) { return a; };
      ^~~~~~~
p97.cpp:46:6: note: previous declaration as '<lambda(auto:5, auto:6&&)> glambda'
 auto glambda = [](auto a, auto&& b) { return a < b; };
      ^~~~~~~
p97.cpp:70:18: error: cannot convert '<lambda(auto:5, auto:6&&)>' to 'int (*)(int)' in initialization
 int (*fp)(int) = glambda;
                  ^~~~~~~
p97.cpp:80:39: error: 'declval' was not declared in this scope
 decltype(lambda_call_operator_invoker(declval<T>())) (*)(T);
                                       ^~~~~~~
p97.cpp:80:39: note: suggested alternative:
In file included from /usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/bits/move.h:54:0,
                 from /usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/bits/nested_exception.h:40,
                 from /usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/exception:143,
                 from /usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/ios:39,
                 from /usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/ostream:38,
                 from /usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/iostream:39,
                 from p97.cpp:5:
/usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/type_traits:2254:5: note:   'std::declval'
     declval() noexcept
     ^~~~~~~
p97.cpp:80:39: error: 'declval' was not declared in this scope
 decltype(lambda_call_operator_invoker(declval<T>())) (*)(T);
                                       ^~~~~~~
p97.cpp:80:39: note: suggested alternative:
In file included from /usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/bits/move.h:54:0,
                 from /usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/bits/nested_exception.h:40,
                 from /usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/exception:143,
                 from /usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/ios:39,
                 from /usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/ostream:38,
                 from /usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/iostream:39,
                 from p97.cpp:5:
/usr/local/Cellar/gcc/7.3.0_1/include/c++/7.3.0/type_traits:2254:5: note:   'std::declval'
     declval() noexcept
     ^~~~~~~
p97.cpp:80:48: error: expected primary-expression before '>' token
 decltype(lambda_call_operator_invoker(declval<T>())) (*)(T);
                                                ^
p97.cpp:80:50: error: expected primary-expression before ')' token
 decltype(lambda_call_operator_invoker(declval<T>())) (*)(T);
                                                  ^
p97.cpp:81:28: error: 'fptr_t' does not name a type; did you mean 'fpos_t'?
 template<class T> operator fptr_t<T>() const
                            ^~~~~~
                            fpos_t
p97.cpp: In member function 'auto Closure::operator()(T) const':
p97.cpp:73:48: error: expected primary-expression before '...' token
 template<class T> auto operator()(T t) const { ... }
                                                ^~~
p97.cpp: In static member function 'static auto Closure::lambda_call_operator_invoker(T)':
p97.cpp:77:1: error: expected primary-expression before '...' token
 ...
 ^~~
p97.cpp: At global scope:
p97.cpp:91:6: error: conflicting declaration 'auto glambda'
 auto glambda = [](auto a) { return a; };
      ^~~~~~~
p97.cpp:46:6: note: previous declaration as '<lambda(auto:5, auto:6&&)> glambda'
 auto glambda = [](auto a, auto&& b) { return a < b; };
      ^~~~~~~
p97.cpp:92:3: error: expected constructor, destructor, or type conversion before '(' token
 f1(glambda); // OK
   ^
p97.cpp:93:3: error: expected constructor, destructor, or type conversion before '(' token
 f2(glambda); // error: ID is not convertible
   ^
p97.cpp:94:2: error: expected constructor, destructor, or type conversion before '(' token
 g(glambda); // error: ambiguous
  ^
p97.cpp:95:2: error: expected constructor, destructor, or type conversion before '(' token
 h(glambda); // OK: calls #3 since it is convertible from ID
  ^
p97.cpp:100:7: error: expected constructor, destructor, or type conversion before '(' token
 GL_int(3); // OK: same as GL(3)
       ^
p97.cpp:107:1: error: non-constant condition for static assertion
 static_assert(Fwd(NC,3) == 3); // ill-formed
 ^~~~~~~~~~~~~
p97.cpp:107:18:   in constexpr expansion of 'Fwd.<lambda(int (*)(int), auto:17)>(NC.<lambda(auto:19)>::operator int (*)(int)<int>(), 3)'
p97.cpp:107:1: error: call to non-constexpr function '<lambda(auto:19)> [with auto:19 = int]'
p97.cpp:106:20: note: '<lambda(auto:19)> [with auto:19 = int]' is not usable as a constexpr function because:
 auto NC = [](auto a) { static int s; return a; };
                    ^
p97.cpp:106:35: error: 's' declared 'static' in 'constexpr' function
 auto NC = [](auto a) { static int s; return a; };
                                   ^
p97.cpp: In member function 'void S2::f(int)':
p97.cpp:123:6: warning: explicit by-reference capture of 'i' redundant with by-reference capture default
 [&, &i]{ }; // error: i preceded by & when & is the default
      ^
p97.cpp:125:5: warning: explicit by-copy capture of 'this' redundant with by-copy capture default
 [=, this]{ }; // error: this when = is the default
     ^~~~
p97.cpp:126:5: warning: already captured 'i' in lambda expression
 [i, i]{ }; // error: i repeated
     ^
p97.cpp:127:9: warning: already captured 'this' in lambda expression
 [this, *this]{ }; // error: this appears twice
         ^~~~
p97.cpp: In lambda function:
p97.cpp:159:14: error: 'j' is not captured
 auto m4 = [&,j] { // error: j not captured by m3
              ^
p97.cpp:158:18: note: the lambda has no capture-default
 auto m3 = [this,m] {
                  ^
p97.cpp:157:5: note: 'int j' declared here
 int j = 40;
     ^
p97.cpp: In lambda function:
p97.cpp:160:9: error: 'n' is not captured
 int x = n; // error: n implicitly captured by m4
         ^
p97.cpp:158:18: note: the lambda has no capture-default
 auto m3 = [this,m] {
                  ^
p97.cpp:155:15: note: 'int n' declared here
 void work(int n) {
               ^
p97.cpp:164:6: error: 'i' is not captured
 x += i; // error: i is outside of the reaching scope
      ^
p97.cpp:158:18: note: the lambda has no capture-default
 auto m3 = [this,m] {
                  ^
p97.cpp:143:13: note: 'int i' declared here
 void f1(int i) {
             ^
p97.cpp: At global scope:
p97.cpp:175:1: error: expected identifier before 'int'
 int main(int argc, char *argv[], char *envp[]){
 ^~~
p97.cpp:175:46: error: two or more data types in declaration of 'main'
 int main(int argc, char *argv[], char *envp[]){
                                              ^
p97.cpp: In lambda function:
p97.cpp:193:1: error: expected ';' before '}' token
 }();
 ^
p97.cpp: In lambda function:
p97.cpp:197:10: error: 'this' was not captured for this lambda function
 return [*this] { }; // error: *this not captured by outer lambda-expression
          ^~~~
p97.cpp: In function 'void f2()':
p97.cpp:205:35: error: default argument '<lambda closure object>f2()::<lambda()>{i}.f2()::<lambda()>()' uses local variable 'i'
 void g1(int = ([i]{ return i; })()); // ill-formed
                                   ^
p97.cpp:206:35: error: default argument '<lambda closure object>f2()::<lambda()>{i}.f2()::<lambda()>()' uses local variable 'i'
 void g2(int = ([i]{ return 0; })()); // ill-formed
                                   ^
p97.cpp:207:35: error: default argument '<lambda closure object>f2()::<lambda()>{i}.f2()::<lambda()>()' uses local variable 'i'
 void g3(int = ([=]{ return i; })()); // ill-formed
                                   ^
p97.cpp:213:10: error: a function-definition is not allowed here before '{' token
 void g() {
          ^
p97.cpp:226:10: error: 'the' was not declared in this scope
 Example: the nested lambda expressions and invocations below will output 123234.
          ^~~
p97.cpp:228:12: error: 'a' was not declared in this scope
 auto m1 = [a, &b, &c]() mutable {
            ^
p97.cpp:228:16: warning: capture of variable 'b' with non-automatic storage duration
 auto m1 = [a, &b, &c]() mutable {
                ^
p97.cpp:47:6: note: 'bool b' declared here
 bool b = glambda(3, 3.14); // OK
      ^
p97.cpp:228:20: error: 'c' was not declared in this scope
 auto m1 = [a, &b, &c]() mutable {
                    ^
p97.cpp: In lambda function:
p97.cpp:229:12: error: 'a' is not captured
 auto m2 = [a, b, &c]() mutable {
            ^
p97.cpp:228:21: note: the lambda has no capture-default
 auto m1 = [a, &b, &c]() mutable {
                     ^
p97.cpp:228:12: note: '<typeprefixerror>a' declared here
 auto m1 = [a, &b, &c]() mutable {
            ^
p97.cpp:229:15: warning: capture of variable 'b' with non-automatic storage duration
 auto m2 = [a, b, &c]() mutable {
               ^
p97.cpp:47:6: note: 'bool b' declared here
 bool b = glambda(3, 3.14); // OK
      ^
p97.cpp:229:19: error: 'c' is not captured
 auto m2 = [a, b, &c]() mutable {
                   ^
p97.cpp:228:21: note: the lambda has no capture-default
 auto m1 = [a, &b, &c]() mutable {
                     ^
p97.cpp:228:20: note: '<typeprefixerror>c' declared here
 auto m1 = [a, &b, &c]() mutable {
                    ^
p97.cpp: In lambda function:
p97.cpp:230:14: error: 'a' is not captured
 std::cout << a << b << c;
              ^
p97.cpp:229:20: note: the lambda has no capture-default
 auto m2 = [a, b, &c]() mutable {
                    ^
p97.cpp:228:12: note: '<typeprefixerror>a' declared here
 auto m1 = [a, &b, &c]() mutable {
            ^
p97.cpp:230:24: error: 'c' is not captured
 std::cout << a << b << c;
                        ^
p97.cpp:229:20: note: the lambda has no capture-default
 auto m2 = [a, b, &c]() mutable {
                    ^
p97.cpp:228:20: note: '<typeprefixerror>c' declared here
 auto m1 = [a, &b, &c]() mutable {
                    ^
p97.cpp:231:1: error: 'a' is not captured
 a = 4; b = 4; c = 4;
 ^
p97.cpp:229:20: note: the lambda has no capture-default
 auto m2 = [a, b, &c]() mutable {
                    ^
p97.cpp:228:12: note: '<typeprefixerror>a' declared here
 auto m1 = [a, &b, &c]() mutable {
            ^
p97.cpp:231:15: error: 'c' is not captured
 a = 4; b = 4; c = 4;
               ^
p97.cpp:229:20: note: the lambda has no capture-default
 auto m2 = [a, b, &c]() mutable {
                    ^
p97.cpp:228:20: note: '<typeprefixerror>c' declared here
 auto m1 = [a, &b, &c]() mutable {
                    ^
p97.cpp: In lambda function:
p97.cpp:233:1: error: 'a' is not captured
 a = 3; b = 3; c = 3;
 ^
p97.cpp:228:21: note: the lambda has no capture-default
 auto m1 = [a, &b, &c]() mutable {
                     ^
p97.cpp:228:12: note: '<typeprefixerror>a' declared here
 auto m1 = [a, &b, &c]() mutable {
            ^
p97.cpp:233:15: error: 'c' is not captured
 a = 3; b = 3; c = 3;
               ^
p97.cpp:228:21: note: the lambda has no capture-default
 auto m1 = [a, &b, &c]() mutable {
                     ^
p97.cpp:228:20: note: '<typeprefixerror>c' declared here
 auto m1 = [a, &b, &c]() mutable {
                    ^
p97.cpp: In function 'void f2()':
p97.cpp:240:11: error: a function-definition is not allowed here before '{' token
 void f3() {
           ^
p97.cpp:250:1: error: a template declaration cannot appear at block scope
 template<class... Args>
 ^~~~~~~~
p97.cpp:262:1: error: expected '}' at end of input
 }
 ^

検討事項

 コンパイルエラーにならない修正。

参考資料

コンパイル用shell script C版(clangとgcc)とC++版(clang++とg++)
https://qiita.com/kaizen_nagoya/items/74220c0577a512c2d7da

Clang/Clang++(LLVM) gcc/g++(GNU) コンパイラ警告等比較
https://qiita.com/kaizen_nagoya/items/9a82b958cc3aeef0403f

Qiitaに投稿するCのStyle例(暫定)
https://qiita.com/kaizen_nagoya/items/946df1528a6a1ef2bc0d

MISRA C++ 5-0-16
https://qiita.com/kaizen_nagoya/items/7df2d4e05db724752a74

C++ Templates Part1 BASICS Chapter 3. Class Templates 3.2 Use of Class Template Stack stack1test.cpp
https://qiita.com/kaizen_nagoya/items/cd5fc49106fad5a4e9ed

ISO/IEC TS 17961:2013 C Secure Coding Rules(1) All list(to be confirmed)
https://qiita.com/kaizen_nagoya/items/54e056195c4f11b850a1

C言語(C++)に対する誤解、曲解、無理解、爽快。
https://qiita.com/kaizen_nagoya/items/3f3992c9722c1cee2e3a

C Puzzle Bookの有り難み5つ、C言語規格及びCコンパイラの特性を認識
https://qiita.com/kaizen_nagoya/items/d89a48c1536a02ecdec9

'wchar.h' file not found で困った clang++ macOS
https://qiita.com/kaizen_nagoya/items/de15cd46d657517fac11

Open POSIX Test Suiteの使い方を調べはじめました
https://qiita.com/kaizen_nagoya/items/644d5e407f5faf96e6dc

MISRA-C 2012 Referenceに掲載している文献の入手可能性を確認
https://qiita.com/kaizen_nagoya/items/96dc8b125e462d5575bb

どうやって MISRA Example Suiteをコンパイルするか
https://qiita.com/kaizen_nagoya/items/fbdbff5ff696e2ca7f00

MISRA C まとめ #include
https://qiita.com/kaizen_nagoya/items/f1a79a7cbd281607c7c9

「C++完全理解ガイド」の同意できること上位7
https://qiita.com/kaizen_nagoya/items/aa5744e0c4a8618c7671

文書履歴

ver. 0.10 初稿 2080417
ver. 0.11 URL追記 20230215

最後までおよみいただきありがとうございました。

いいね 💚、フォローをお願いします。

Thank you very much for reading to the last sentence.

Please press the like icon 💚 and follow me for your happy life.

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?