23

GCC 4.7.2 はこれをコンパイルします。

constexpr int i = 5;
[]{ std::integral_constant< int, i >(); }; // nonstandard: i not captured

しかし、これではありません:

constexpr int i = 5;
[&i]{ std::integral_constant< int, i >(); }; // GCC says i not constexpr

C++11 §5.1.2/15 によると、後者の例は私には正しいように見えます。

エンティティが暗黙的または明示的にキャプチャされ、コピーによってキャプチャされない場合、エンティティは参照によってキャプチャされます。追加の名前のない非静的データ メンバーが、参照によってキャプチャされたエンティティのクロージャ型で宣言されているかどうかは指定されていません。

ラムダ内のキャプチャされたオブジェクトは、単なる参照ではなくi、囲んでいるスコープ内の変数を参照しているようです。constexprconst

標準では、値によるキャプチャの使用はラムダ オブジェクトの対応するメンバーの使用に変換されると明示的に述べています。そして、5.1.2 は私の解釈が正しいことを暗示していると思います。

参照によるキャプチャが、囲んでいるスコープまたは参照内のオブジェクトを参照するかどうかを明示的に示すものはありますか?

4

2 に答える 2

12

2 番目のtemplate-argument tostd::integral_constant< int, i >は、非形式、具体的には整数型または列挙型(14.3.2p1 bullet 1) のtemplate-parameter用であり、型の変換された定数式でなければなりません。int

lambda-expressionでは、エンティティーが複合ステートメント (5.1.2p11) で ODR 使用されている場合に、暗黙のキャプチャーが発生します。明示的なテンプレートのインスタンス化で変換された定数式を使用することは、odr-use (3.2p3) ではないため、最初の例は有効です。

2 番目の例では、gcc がそれを拒否するのは間違っていると思います。5.1.2p17 はメモで次のように述べています。

Odr -use ではないid-expressionは元のエンティティを参照し、クロージャー型のメンバーを参照することはありません。

この段落全体ではコピーによるキャプチャについて説明していますが、このルールを参照によるキャプチャにも適用しない理由はありません。これに関する標準が不明確であることは当然のことです。参照によって変換された定数式で使用できるエンティティをキャプチャする理由はまったくありません。

于 2012-11-20T10:52:34.627 に答える
0

まず、Ubuntu 12.04 で gcc 4.6.3 と clang 3.0 を使用した観察を確認できます。

私は C++11 標準 (ドラフトのみ) を持っていないので、それについてコメントすることはできません。しかし、私の理解から、同等のステートメントを見てください

constexpr int i = 5;
const int &j = i;
std::integral_constant<int, j>();

j「整数定数」ではないため、gccもclangもこれをコンパイルしません。

于 2012-11-20T10:39:04.897 に答える