タグ付けされた質問 「language-lawyer」

プログラミング言語と環境の正式または信頼できる仕様の複雑さについての質問。

4
非ブール戻り値との等価比較をオーバーロードすると、C ++ 20の重大な変更またはclang-trunk / gcc-trunkの回帰?
次のコードは、c ++ 17モードではclang-trunkで正常にコンパイルされますが、c ++ 2a(今後のc ++ 20)モードでは機能しません。 // Meta struct describing the result of a comparison struct Meta {}; struct Foo { Meta operator==(const Foo&) {return Meta{};} Meta operator!=(const Foo&) {return Meta{};} }; int main() { Meta res = (Foo{} != Foo{}); } また、gcc-trunkまたはclang-9.0.0でも問題なくコンパイルできます。https://godbolt.org/z/8GGT78 clang-trunkおよび-std=c++2a: <source>:12:19: error: use of overloaded …

1
山かっこのGCCの実装には次のものが含まれます。なぜそれは以下に説明されているとおりでなければならないのですか?
このドキュメントのセクション2.6計算済みインクルードには、次の段落があります。 行が<トークンで始まり、>トークンを含むトークンストリームに展開される場合、<と最初の>の間のトークンが結合されて、含まれるファイル名が形成されます。トークン間の空白は1つのスペースに削減されます。その後、最初の<の後のスペースは保持されますが、閉じる>の前のスペースは無視されます。CPPは山かっこインクルードのルールに従ってファイルを検索します。 これは実装で定義されていることはわかっていますが、なぜGCCにとってこのようにする必要があるのですか?上記の強調表示された文を具体的に参照しています。 編集 上で引用したものの前の3番目の段落が次のことを言っていることに気づきました。 マクロを定義するときは注意が必要です。#defineテキストではなくトークンを保存します。プリプロセッサは、マクロがの引数として使用されることを知る方法がない#includeため、ヘッダー名ではなく通常のトークンを生成します。文字列定数に十分近い二重引用符を含むインクルードを使用する場合、これが問題を引き起こすことはほとんどありません。 ただし、山括弧を使用すると、問題が発生する可能性があります。 ここでどんな問題が指摘されているか知っていますか?
11 c++  c  gcc  language-lawyer 

1
コンパイラは、無関係なインターフェイスタイプで呼び出されたときに、クラスタイプパラメータを持つこのジェネリックメソッドを選択するのはなぜですか?
次の2つのクラスとインターフェースを検討してください。 public class Class1 {} public class Class2 {} public interface Interface1 {} mandatoryオーバーロードされたメソッドを呼び出すための2番目の呼び出しが、との関係がないClass2場合getInterface1、なぜですか?Interface1Class2 public class Test { public static void main(String[] args) { Class1 class1 = getClass1(); Interface1 interface1 = getInterface1(); mandatory(getClass1()); // prints "T is not class2" mandatory(getInterface1()); // prints "T is class2" mandatory(class1); // prints "T is …

2
Tは `std :: declval <T>`で使用される完全な型である必要がありますか?
この例を見てみましょう(ここから来ます): #include &lt;type_traits&gt; #include &lt;iostream&gt; template &lt;typename U&gt; struct A { }; struct B { template &lt;typename F = int&gt; A&lt;F&gt; f() { return A&lt;F&gt;{}; } using default_return_type = decltype(std::declval&lt;B&gt;().f()); }; int main() { B::default_return_type x{}; std::cout &lt;&lt; std::is_same&lt; B::default_return_type, A&lt;int&gt;&gt;::value; } それはgcc9.2でエラーなしでコンパイルしますが、gcc7.2とclang 10.0.0 Bは完了していないことについて不平を言います。Clangsエラーは: prog.cc:11:58: error: member access into …

2
C ++テンプレートテンプレート引数タイプの控除
文字列のコンテナを調べて、パターンの一致を見つけて出力するコードがあります。テンプレート化された関数fooで印刷が実行されます コード #include &lt;iostream&gt; #include &lt;algorithm&gt; #include &lt;iterator&gt; #include &lt;vector&gt; #include &lt;string&gt; #include &lt;tuple&gt; #include &lt;utility&gt; template&lt;typename Iterator, template&lt;typename&gt; class Container&gt; void foo(Iterator first, Container&lt;std::pair&lt;Iterator, Iterator&gt;&gt; const &amp;findings) { for (auto const &amp;finding : findings) { std::cout &lt;&lt; "pos = " &lt;&lt; std::distance(first, finding.first) &lt;&lt; " "; std::copy(finding.first, finding.second, std::ostream_iterator&lt;char&gt;(std::cout)); …

1
CHAR_MAXに設定されたchar値は、CHAR_MINにラップアラウンドすることが保証されていますか?
私のコード: #include &lt;stdio.h&gt; #include &lt;limits.h&gt; int main() { char c = CHAR_MAX; c += 1; printf("CHAR_MIN=%d CHAR_MAX=%d c=%d (%c)\n", CHAR_MIN, CHAR_MAX, c, c); } 出力: CHAR_MIN=-128 CHAR_MAX=127 c=-128 () char変数セットをにインクリメントするとCHAR_MAX、に戻りCHAR_MINます。この動作は保証されていますか?それとも、未定義の動作または実装固有の動作になりますか?C99標準はこれについて何と言っていますか? [注:charまたはCにCHAR_MAX(127)より大きい値を指定するとどうなりますか。charc = 129が-127に変換されるのはなぜですか?彼らは範囲外の値に値を増分するのではなく範囲外の値を割り当てることについて話しているので、この質問には触れません。]

1
プロパティのデフォルト値を介して関係を変更しようとすると、予期しないInvalidOperationExceptionが発生する
以下のサンプルコードでは、実行時に次の例外が発生しdb.Entry(a).Collection(x =&gt; x.S).IsModified = trueます。 System.InvalidOperationException: 'エンティティタイプ' B 'のインスタンスは、キー値' {Id:0} 'の別のインスタンスが既に追跡されているため追跡できません。既存のエンティティをアタッチするときは、特定のキー値を持つエンティティインスタンスが1つだけアタッチされるようにしてください。 Bのインスタンスをアタッチする代わりに追加しないのはなぜですか? 奇妙なことに、のドキュメントにIsModifiedはInvalidOperationException、例外の可能性が明記されていません。無効なドキュメントまたはバグ? 私はこのコードが奇妙であることを知っていますが、奇妙なegdeのケースでefコアがどのように機能するかを理解するためだけにそれを書きました。私が欲しいのは説明ではなく、回避策です。 using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; class Program { public class A { public int Id { get; set; } public ICollection&lt;B&gt; S { get; set; } = new List&lt;B&gt;() { new …

3
異なるコンパイラでのC ++とCの間の符号なしビットフィールド整数式の一貫性のない切り捨て
編集2: 以前にC ++ソースファイルに存在していた関数がそのままCファイルに移動され、誤った結果が返され始めたときに、奇妙なテストエラーをデバッグしていました。以下のMVEにより、GCCでの問題を再現できます。しかし、気まぐれでClangを使用して(そして後でVSを使用して)例をコンパイルすると、異なる結果が得られました!これをコンパイラの1つのバグとして扱うのか、CまたはC ++標準で許可されている未定義の結果の明示として扱うのか、私にはわかりません。奇妙なことに、どのコンパイラーも式に関する警告を出しませんでした。 犯人はこの表現です: ctl.b.p52 &lt;&lt; 12; ここでp52は、と入力されuint64_tます。組合の一部でもありcontrol_tます(下記参照)。結果は64ビットに収まるため、シフト操作はデータを失わない。ただし、Cコンパイラを使用している場合、GCCは結果を52ビットに切り捨てることを決定します。C ++コンパイラでは、結果の64ビットがすべて保持されます。 これを説明するために、以下のサンプルプログラムは、同一の本体を持つ2つの関数をコンパイルし、それらの結果を比較します。c_behavior()Cソースファイルとcpp_behavior()C ++ファイルに配置されmain()、比較を行います。 サンプルコードを含むリポジトリ:https : //github.com/grigory-rechistov/c-cpp-bitfields ヘッダーcommon.hは、64ビット幅のビットフィールドと整数の和集合を定義し、2つの関数を宣言します。 #ifndef COMMON_H #define COMMON_H #include &lt;stdint.h&gt; typedef union control { uint64_t q; struct { uint64_t a: 1; uint64_t b: 1; uint64_t c: 1; uint64_t d: 1; uint64_t e: 1; uint64_t f: 1; uint64_t g: …

2
関数型の引数のテンプレート引数の控除
次のプログラムを検討してください。 #include &lt;iostream&gt; template &lt;typename T&gt; void f( void ( *fn )( T ) ) { fn( 42 ); } void g( int x ) { std::cout &lt;&lt; "g( " &lt;&lt; x &lt;&lt; " );\n"; } int main() { f( g ); } プログラムは正常にコンパイルされ、その出力は g( 42 ); 今度は、非テンプレート関数の名前を変更してみましょうgにf。 #include &lt;iostream&gt; …

1
2番目のimplを追加すると、なぜ引数のderef強制が妨げられるのですか?
impl Add&lt;char&gt; for Stringを標準ライブラリに追加しようとしたときにこの問題に遭遇しました。しかし、オペレーターのシェニガンがなくても、簡単に複製できます。私たちはこれから始めます: trait MyAdd&lt;Rhs&gt; { fn add(self, rhs: Rhs) -&gt; Self; } impl MyAdd&lt;&amp;str&gt; for String { fn add(mut self, rhs: &amp;str) -&gt; Self { self.push_str(rhs); self } } 十分に単純です。これにより、次のコードがコンパイルされます。 let a = String::from("a"); let b = String::from("b"); MyAdd::add(a, &amp;b); この場合、2番目の引数式(&amp;b)のタイプはであることに注意してください&amp;String。次に、それがderef-coercedされ&amp;str、関数呼び出しが機能します。 ただし、次の実装を追加してみましょう。 impl MyAdd&lt;char&gt; for String { fn …

2
nullポインタ引数と不可能な事後条件を使用して標準例外を構築します
次のプログラムを検討してください。 #include&lt;stdexcept&gt; #include&lt;iostream&gt; int main() { try { throw std::range_error(nullptr); } catch(const std::range_error&amp;) { std::cout &lt;&lt; "Caught!\n"; } } libstdc ++を使用したGCCおよびClang std::terminateは、メッセージを表示してプログラムを呼び出し、中止します terminate called after throwing an instance of 'std::logic_error' what(): basic_string::_S_construct null not valid 例外の構築時にlibc ++のClangがsegfaultします。 godboltを参照してください。 コンパイラは標準に準拠していますか?標準の関連セクション[diagnostics.range.error](C ++ 17 N4659)は言っていstd::range_error有するconst char*好まれるべきであるコンストラクタのオーバーロードconst std::string&amp;オーバーロード。このセクションでは、コンストラクターの前提条件についても述べておらず、事後条件についてのみ述べています。 事後条件:strcmp(what(), what_­arg) == 0。 what_argnullポインターの場合、この事後条件は常に未定義の動作を持っています。つまり、これは私のプログラムにも未定義の動作があり、両方のコンパイラーが準拠して動作することを意味しますか?そうでない場合、標準でそのような不可能な事後条件をどのように読むべきですか? 考え直してみれば、それは私のプログラムにとって未定義の動作を意味しているに違いないと思います。そうしないと、(有効な)ヌル終了文字列を指さないポインタも許可されるため、明らかに意味がありません。 …

1
存続期間が終了したオブジェクトのメンバー関数コルーチンを再開するのはUBですか?
この質問は、このコメントから生じています:C ++ 20コルーチンのラムダ寿命の説明 この例について: auto foo() -&gt; folly::coro::Task&lt;int&gt; { auto task = []() -&gt; folly::coro::Task&lt;int&gt; { co_return 1; }(); return task; } したがって、問題は、によって返されたコルーチンを実行するfooとUBになるかどうかです。 (オブジェクトのライフタイムが終了した後の)メンバー関数の「呼び出し」はUBです。http://eel.is/c++draft/basic.life#6.2 ...オブジェクトが配置される、または配置された保管場所のアドレスを表すポインターは、限られた方法でのみ使用できます。[...]次の場合、プログラムは未定義の動作をします。 [...] -ポインタは非静的データメンバにアクセスしたりするために使用されるオブジェクトの非静的メンバ関数を呼び出し、または ただし、この例では: ()ラムダの有効期間中にラムダの演算子が呼び出されます その後、中断され、 次にラムダが破壊され、 その後、メンバー関数(演算子())はある時点で再開されます。 この再開は未定義の動作と見なされますか?

1
不特定の暗黙的なオブジェクトの作成
以来P0593低レベルのオブジェクトの操作のためのオブジェクトの暗黙の作成は、オブジェクトが現在作成され、承認された暗黙的に C ++ 20で。 具体的に提案により導入された文言は、(のような特定の操作が可能にstd::malloc)自動的に特定の種類のオブジェクトの寿命を作成して開始するには、いわゆる暗黙の一生のタイプ、場合このようなオブジェクトの導入は持っているそれ以外の場合は未定義の動作でプログラムを引き起こします定義された動作。[intro.object] / 10を参照してください。 ドラフトはさらに、プログラムで定義された動作を与えるために暗黙的に作成できるそのようなオブジェクトの複数のセットがある場合、これらのセットのどれが作成されるかは不特定であると述べています。(関連する文は、私がアクセスできた最後の提案リビジョンR5には存在しないようですが、ドラフトコミットにあります。) 暗黙的に作成されたオブジェクトセットのこの選択が観察可能なプログラムは実際にありますか?言い換えると、この新しいルールを通じて、定義されているが特定されていない動作を伴うプログラムがあり、(複数の可能なオブジェクトのうち)作成された暗黙オブジェクトのタイプのセットを出力から推測できるようになっていますか? または、この文は、抽象的なマシンでのプログラムの実行を(観察可能な影響なしに)明確にすることだけを目的としていましたか?

2
C ++がFoo <T> :: Foo(T &&)の呼び出しでTを推定できないのはなぜですか?
次のテンプレート構造があるとします。 template&lt;typename T&gt; struct Foo { Foo(T&amp;&amp;) {} }; これはコンパイルTされ、次のように推定されますint。 auto f = Foo(2); しかし、これはコンパイルされません:https : //godbolt.org/z/hAA9TE int x = 2; auto f = Foo(x); /* &lt;source&gt;:12:15: error: no viable constructor or deduction guide for deduction of template arguments of 'Foo' auto f = Foo(x); ^ &lt;source&gt;:7:5: note: candidate function …

2
C ++-ここで「テンプレート」キーワードが必要なのはなぜですか?
私は次のコードを持っています: template &lt;typename TC&gt; class C { struct S { template &lt;typename TS&gt; void fun() const {} }; void f(const S&amp; s) { s.fun&lt;int&gt;(); } }; // Dummy main function int main() { return 0; } これをgcc 9.2とclang(9.0)の両方でビルドすると、templateを呼び出すために必要なキーワードが原因で、コンパイルエラーが発生しますfun。Clangのショー: error: use 'template' keyword to treat 'fun' as a dependent template name …

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.