38126
C++17の以下のコードについて質問です。

```

    #include <iostream>
    
    template <typename F>
    auto func(F f)
    {
        constexpr auto x = f();
        return x;
    }
    
    int main()
    {
        auto x = func( [](){ return "abc"; } );
        std::cout << x << std::endl;
    }
    
```

このコードがg++7.2.0およびclang5.0.0、`-std=c++1z -Wall -Wextra
-pedantic`で警告なくコンパイルが通ったのですが、ラムダ式を渡してfuncの引数からconstexpr変数を定義できていることについて、C++17の規格上、不適格や未定義動作等になっているかいないかどうかをご教示いただきたく存じます。  
よろしくお願いします。
CC BY-SA 3.0
2017-09-22T13:38:49.090
38123
2017-09-26T05:57:07.970
25520
question
c++
ラムダ式を使って関数の引数からconstexpr変数を定義できたことに関する質問
質問中のコードではconstexprを付けても付けなくても結果が変わりません。真にコンパイル時定数が必要ならば、下記コードで実現・確認が可能です：

```

    template <typename F>
    constexpr auto func(F f)
    {
      constexpr auto x = f();
      static_assert(x == 42);
      return x;
    }
    
    int main()
    {
      constexpr auto x = func( [](){ return 42; } );
      static_assert(x == 42);
    }
    
```

* * *

N4659 [expr.prim.lambda.closure]/p4
で、条件をみたせばクロージャオブジェクトの`operator()`メンバ関数が、暗黙にconstexpr functionとみなされる旨が記載されています。

> [...] The function call operator or any given operator template
> specialization is a constexpr function if either the corresponding _lambda-
> expression_ 's _parameter-declarationclause_ is followed by `constexpr`, or
> it satisfies the requirements for a constexpr function (10.1.5). [...] [
> _Example:_
```

>     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
>  
```

>
> \-- _end example_ ]
CC BY-SA 3.0
2017-09-22T13:51:34.613
38126
2017-09-26T05:57:07.970
2017-09-26T05:57:07.970
49
49
38123
answer