coding
C++N4741

C++N4741(39)8.4.5.1 Closure types [expr.prim.lambda.closure]p88

はじめに(Introduction)

C++N4741 Working Draft, Standard for Programming Language C++
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4741.pdf

C++N4741は、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)との関係も調査中です。
何か、抜け漏れ、耳より情報がありましたらおしらせくださると幸いです。

背景(back ground)

C/C++でコンパイルエラーが出ると、途方にくれることがしばしばあります。
何回かに1回は、該当するエラーが検索できます。
ただ、条件が違っていて、そこでの修正方法では目的を達成しないこともしばしばです。いろいろな条件のコンパイルエラーとその対応方法について、広く記録することによって、いつか同じエラーに遭遇した時にやくに立つことを目指しています。

この半年の間で、三度、自分のネットでの記録に助けられたことがあります。
また過去に解決できなかった記録を10種類以上、最近になって解決できたことがあります。それは、主に次の3つの情報に基づいています。

https://stackoverflow.com
https://cpprefjp.github.io
http://ja.cppreference.com/

また
https://researchmap.jp/joub9b3my-1797580/#_1797580
に記載したサイトのお世話になっています。

作業方針(sequence)

Clang++では-std=c++03, c++17, C++2aの3種類
g++では-std=c++03, c++17の2種類
でコンパイルし、

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

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

初めての CEDD(Compile Error Driven Design) 8回直してコンパイル。
https://qiita.com/kaizen_nagoya/items/9494236aa1753f3fd1e1

https://qiita.com/kaizen_nagoya/items/85c0e92b206883140e89#_reference-f5ba2535f9b0e314ab73コンパイルエラーを記録するとよい理由7つ

C++N4741, 2018 Standard Working Draft on ISO/IEC 14882 sample code compile list

https://qiita.com/kaizen_nagoya/items/3294c014044550896010

C++N4606, 2016符号断片編纂一覧(example code compile list)

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

C++N3242, 2011 sample code compile list on clang++ and g++

https://qiita.com/kaizen_nagoya/items/685b5c1a2c17c1bf1318

編纂器(Compiler)

clang++ --version

clang version 6.0.0 (tags/RELEASE_600/final)
Target: x86_64-apple-darwin17.4.0

g++-7 --version

g++-7 (Homebrew GCC 7.3.0_1) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.

(39)8.4.5.1 Closure types [expr.prim.lambda.closure]p88

No section on C++N4606, 2016, but some examples may be at
(37)5.1.5 Lambda expressions [expr.prim.lambda]p97

https://qiita.com/kaizen_nagoya/items/f0c78ed1d43514053070

No section on C++N3242, 2011, but some examples may be at
C++N3242, 2011 (29) 5.1.2 Lambda expressions
https://researchmap.jp/joo8p5759-1797580/#_1797580

p88.cpp

算譜(source code)

p88.cpp
// C++N4741 Committee Draft, Standard for Programming Language C++
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n741.pdf
const char* msg= "C++N4741(39)8.4.5.1 Closure types [expr.prim.lambda.closure]p88.cpp";
// Edited by Dr. Ogawa Kiyoshi. Compile procedure and results record.

#include <iostream>
#include <cstdlib>
#include <cassert>
#include <type_traits>
using namespace std;

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); // ill-formed

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

template <typename T> concept C1 = /* ... */;
template <std::size_t N> concept C2 = /* ... */;
template <typename A, typename B> concept C3 = /* ... */;
auto f = []<typename T1, C1 T2> requires C2<sizeof(T1) + sizeof(T2)>
(T1 a1, T1 b1, T2 a2, auto a3, auto a4) requires C3<decltype(a4), T2> {
// T2 is a constrained parameter,
// T1 and T2 are constrained by a requires-clause, and
// T2 and the type of a4 are constrained by a trailing requires-clause.
};

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*
    };
  }
};



int main() {
  cout<< msg << endl;
  return EXIT_SUCCESS;
}

編纂・実行結果(compile and go)

g++
$ g++ p88.cpp -std=c++17 -Wall
p88.cpp:29:4: error: expected constructor, destructor, or type conversion before ';' token
 q(); // OK: outputs 1a3.14
    ^
p88.cpp:34:1: error: non-constant condition for static assertion
 static_assert(ID(3) == 3); // OK
 ^~~~~~~~~~~~~
p88.cpp:34:17: error: call to non-constexpr function '<lambda(auto:8)> [with auto:8 = int]'
 static_assert(ID(3) == 3); // OK
               ~~^~~
p88.cpp:39:1: error: non-constant condition for static assertion
 static_assert(ID(NonLiteral{3}).n == 3); // ill-formed
 ^~~~~~~~~~~~~
p88.cpp:39:1: error: temporary of non-literal type 'NonLiteral' in a constant expression
p88.cpp:35:8: note: 'NonLiteral' is not literal because:
 struct NonLiteral {
        ^~~~~~~~~~
p88.cpp:35: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
p88.cpp: In lambda function:
p88.cpp:44:24: error: expected '{' before 'constexpr'
 auto add = [](auto m1) constexpr {
                        ^~~~~~~~~
p88.cpp: At global scope:
p88.cpp:44:24: error: expected ',' or ';' before 'constexpr'
P87-2.CPP
現在検討中

編纂・実行結果(compile and go)

cpla.sh
作業中

検討事項(agenda) coding C++N4741

clang++でコンパイルエラーが多く、g++では少ない背景を調査中。
役に立つまたは意味のあるその他の出力

参考資料(reference)

docker gnu(gcc/g++) and llvm(clang/clang++)
https://qiita.com/drafts/059874ea39c4de64c0f7

[C][C++]の国際規格案の例題をコンパイルするときの課題7つ。
https://qiita.com/kaizen_nagoya/items/5f4b155030259497c4de

C++N4606 Working Draft 2016, ISO/IEC 14882, C++ standardのコード断片をコンパイルするためにしていること
https://qiita.com/kaizen_nagoya/items/a8d7ee2f2e29e76c19c1

コンパイル用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

C++2003とC++2017でコンパイルエラーになるならない事例集
https://qiita.com/kaizen_nagoya/items/a13ea3823441c430edff

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

cpprefjpのdecltypeをコンパイル試験
https://qiita.com/kaizen_nagoya/items/090909af702f0d5d8a67

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++完全理解ガイド」の同意できること上位10
https://qiita.com/kaizen_nagoya/items/aa5744e0c4a8618c7671

文書履歴(document history)

ver. 0.10 初稿 20180507