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

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

1
Haskellパーサーは、数値リテラルでUnicode数字を許可する必要がありますか?
演習として、Haskellのパーサーをゼロから作成しています。レクサーを作成する際に、Haskell 2010レポートの次のルールに気づきました。 数字 → ascDigit | uniDigit ascDigit → 0| 1| …| 9 uniDigit →任意のUnicode 10進数 オクティット → 0| 1| …| 7 hexit → digit | A| …| F| a| …|f 10進数 → 数字 { 数字 } 8進数 → octit { octit } 16進数 → hexit { hexit } 整数 …

1
C ++コンパイラーはどのようにして外部変数を見つけますか?
このプログラムをg ++とclang ++でコンパイルします。違いがあります: g ++は1を出力しますが、clang ++は2を出力 します 。g++:extern変数は最も短いスコープで定義されているようです。 clang ++:extern変数は最短のグローバルスコープで定義されます。 C ++仕様にはその仕様がありますか? main.cpp #include <iostream> static int i; static int *p = &i; int main() { int i; { extern int i; i = 1; *p = 2; std::cout << i << std::endl; } } other.cpp int i; バージョン:g ++:7.4.0 …

2
なぜ `std :: basic_ios`にパブリックコンストラクタがあるのですか?
std::basic_iosパブリックコンストラクタがあります: explicit basic_ios (std::basic_streambuf<CharT,Traits>* sb); IMO、クラスがパブリックコンストラクターを持つ唯一の理由は、プログラムでそのクラスのスタンドアロンインスタンスを使用することです。クラスが存在し、他のクラスがそのクラスの子孫である場合のみ(の場合のようにbasic_ios)、クラスのすべてのコンストラクターはでなければなりませんprotected。のコンストラクタstd::ios_baseはすべて保護されています。しかし、何らかの理由で、標準の設計者はこれをbasic_iospublicの1つのコンストラクターにしました。 basic_iosは、いくつかのストリームタイプの基本クラスとして使用されます。少なくとも、basic_istreamまたはでなかった使用例を想定することはできませんbasic_ostream。ありますか?

2
有効なC ++プログラムを終了しないプログラムですか?
プログラムを終了する必要がありますか?言い換えれば、技術的に未定義の動作を永久に実行するプログラムですか?これは空のループについてではないことに注意してください。「もの」(つまり、観察可能な動作)を永遠に行うプログラムについて話す。 たとえば、次のようなもの: int main() { while (true) { try { get_input(); // calls IO process(); put_output(); // calls IO, has observable behavior // never break, exit, terminate, etc } catch(...) { // ignore all exceptions // don't (re)throw // never go out of loop } } } 経験的にすべての正気なコンパイラは、上記の種類のプログラムに対して期待されるコードを生成するため(これは他のUBのソースがないことを前提としています)、これはより学術的な質問です。そしてもちろん、終了しないプログラム(OS、埋め込み、サーバー)はたくさんあります。しかし、標準は時々風変わりなので、質問です。 接線:「アルゴリズム」の多くの(一部の?)定義では、アルゴリズムを終了する必要があります。つまり、終了しない一連の操作はアルゴリズムとは見なされません。 接線。停止問題は、任意のプログラムが入力に対して終了するかどうかを判別するアルゴリズムが存在できないことを示しています。ただし、この特定のプログラムの場合、メインから抜け出す原因となる分岐がないため、コンパイラーはプログラムが終了しないことを容易に判別できます。質問は言語弁護士なので、これは無関係です。

1
空の基本クラスもメンバー変数であるときに、空の基本最適化が禁止されているのはなぜですか?
空のベース最適化は素晴らしいです。ただし、次の制限があります。 同じ基本型の2つの基本サブオブジェクトはオブジェクト表現内で異なるアドレスを持つ必要があるため、空の基本クラスの1つが最初の非静的データメンバーの型の型または基本でもある場合、空の基本最適化は禁止されています。最も派生したタイプの。 この制限を説明するには、次のコードを検討してください。static_assert失敗します。一方、どちらFooかBarを変更するか、代わりにから継承するBase2と、エラーが回避されます。 #include <cstddef> struct Base {}; struct Base2 {}; struct Foo : Base {}; struct Bar : Base { Foo foo; }; static_assert(offsetof(Bar,foo)==0,"Error!"); 私はこの振る舞いを完全に理解しています。私が理解していないのは、この特定の動作が存在する理由です。見落としではなく明示的な追加であるため、明らかに理由で追加されました。これの根拠は何ですか? 特に、2つの基本サブオブジェクトが異なるアドレスを持つ必要があるのはなぜですか?上記のBarはタイプでfooあり、そのタイプのメンバー変数です。Barの基本クラスがのタイプの基本クラスと関係がある理由foo、またはその逆の理由がわかりません。 実際、私はどちらかと言えば、それを含むインスタンス&fooのアドレスと同じであることを期待しBarます。他の状況で必要になるためです(1)。結局のところ、私はvirtual継承についてBase2特別なことは何もしていません。基本クラスは関係なく空であり、を使用したコンパイルは、この特定のケースでは何も壊れないことを示しています。 しかし、明らかにこの推論はどういうわけか間違っており、この制限が必要になる他の状況があります。 答えがC ++ 11以降であるとしましょう(私は現在C ++ 17を使用しています)。 (1)注:EBOはC ++ 11でアップグレードされ、特にに対して必須になりましたStandardLayoutType(ただしBar、上記でははではありませんStandardLayoutType)。

1
__func__ポインターの2つのconstexprインスタンスの違いはまだconstexprですか?
これは有効なC ++ですか? int main() { constexpr auto sz = __func__ - __func__; return sz; } GCCとMSVCは大丈夫だと思っていますが、Clangはそうではないと思っています:Compiler Explorer。 すべてのコンパイラは、これが問題ないことに同意しています:コンパイラエクスプローラー。 int main() { constexpr auto p = __func__; constexpr auto p2 = p; constexpr auto sz = p2 - p; return sz; } Clangはこれも好きではありませんが、他のものは問題ありません:Compiler Explorer int main() { constexpr auto p = …

1
これはstd :: gcdのバグですか?
私はstd::gcd予期しないことに気付いたこの振る舞いに遭遇しました: #include <iostream> #include <numeric> int main() { int a = -120; unsigned b = 10; //both a and b are representable in type C using C = std::common_type<decltype(a), decltype(b)>::type; C ca = std::abs(a); C cb = b; std::cout << a << ' ' << ca << '\n'; std::cout << …

2
単純なデフォルトコンストラクターがアクションを実行しない場合、mallocを使用して単純な構成可能なオブジェクトを作成できないのはなぜですか?
単純なデフォルトコンストラクターについて、cppreferenceから引用された次の段落を理解するのが困難です。私はstackoverflowを検索しましたが、それでも明確な答えが得られませんでした。助けてください。 単純なデフォルトコンストラクターは、アクションを実行しないコンストラクターです。C言語と互換性のあるすべてのデータ型(POD型)は、簡単にデフォルトで構築できます。ただし、Cとは異なり、単純なデフォルトコンストラクターを持つオブジェクトは、std :: mallocで割り当てられたメモリなど、適切に配置されたストレージを単に再解釈することによって作成することはできません。 具体的には、自明なデフォルトコンストラクターが何もしない場合、ストレージを再解釈して、指定されたタイプのオブジェクトがあるふりをすることができないのはなぜですか?これにより発生する可能性のある未定義の動作の例をいくつか教えていただけますか?

4
C ++ 11でStoreLoadバリアを実現する方法は?
古典的な問題の変形を解決する移植可能なコード(Intel、ARM、PowerPC ...)を記述したいと思います。 Initially: X=Y=0 Thread A: X=1 if(!Y){ do something } Thread B: Y=1 if(!X){ do something } ここでの目標は、両方のスレッドがやっているような状況を避けるためですsomething。(どちらも実行しなくても問題ありません。これは1回だけ実行するメカニズムではありません。)以下の私の推論に欠陥がある場合は、修正してください。 私は次のようにmemory_order_seq_cstアトミックstoresおよびloads を使用して目標を達成できることを認識しています。 std::atomic<int> x{0},y{0}; void thread_a(){ x.store(1); if(!y.load()) foo(); } void thread_b(){ y.store(1); if(!x.load()) bar(); } {x.store(1), y.store(1), y.load(), x.load()}イベントにはいくつかの単一の合計順序が必要であり、プログラムの順序「エッジ」に同意する必要があるため、これは目標を達成します。 x.store(1) 「TOは前に」 y.load() y.store(1) 「TOは前に」 x.load() foo()呼び出された場合、追加のエッジがあります: y.load() 「前に値を読み取る」 y.store(1) bar()呼び出された場合、追加のエッジがあります: …

4
cppreferenceでの緩和された順序付けの説明に誤りはありますか?
cppreference.comのドキュメントstd::memory_orderには、緩和された順序付けの例があります。 ゆるやかな注文 タグ付けさmemory_order_relaxedれたアトミック操作は同期操作ではありません。同時メモリアクセスに順序を課すことはありません。原子性と変更順序の一貫性のみが保証されます。 たとえば、xとyが最初はゼロの場合、 // Thread 1: r1 = y.load(std::memory_order_relaxed); // A x.store(r1, std::memory_order_relaxed); // B // Thread 2: r2 = x.load(std::memory_order_relaxed); // C y.store(42, std::memory_order_relaxed); // D は、r1 == r2 == 42を生成することを許可されています。なぜなら、Aはスレッド1内でBの前にシーケンスされ、Cはスレッド2内でDの前にシーケンスされるからです。 xの変更順序でCの前に表示されます。yに対するDの副作用はスレッド1の負荷Aに見え、xに対するBの副作用はスレッド2の負荷Cに見える可能性があります。特に、これはDがCの前に完了する場合に発生する可能性があります。スレッド2、コンパイラの並べ替えまたは実行時のいずれかが原因。 「Cはスレッド2内でDの前にシーケンスされます」と書かれています。 評価順にあるsequenced-beforeの定義によれば、AがBの前にシーケンス化されている場合、Aの評価はBの評価が始まる前に完了します。Cはスレッド2内でDの前に順序付けられているため、Dが始まる前にCを完了する必要があるため、スナップショットの最後の文の条件部分は決して満たされません。

2
ラムダでstatic_assertを指定したconstexprの場合、どのコンパイラが正しいですか?
static_assertでa if constexprを使用する場合は、条件をいくつかのテンプレートパラメータに依存させる必要があります。興味深いことに、コードがラムダでラップされている場合、gccとclangは一致しません。 次のコードはgccでコンパイルされますが、clang if constexprがtrueでなくても、clangはアサートをトリガーします。 #include <utility> template<typename T> constexpr std::false_type False; template<typename T> void foo() { auto f = [](auto x) { constexpr int val = decltype(x)::value; if constexpr(val < 0) { static_assert(False<T>, "AAA"); } }; f(std::integral_constant<int, 1>{}); } int main() { foo<int>(); } ここでライブ例。 それは簡単に置き換えることによって固定することが可能False<T>でFalse<decltype(x)>。 だから問題は:どのコンパイラーが正しいのか?の状態static_assertはに依存しているので、gccは正しいと思いますTが、よくわかりません。

2
Derived1 :: BaseとDerived2 :: Baseは同じ型を参照していますか?
MSVC、Clang、およびGCCはこのコードに同意しません。 struct Base { int x; }; struct Der1 : public Base {}; struct Der2 : public Base {}; struct AllDer : public Der1, public Der2 { void foo() { Der1::Base::x = 5; } }; ゴッドボルト GCC: <source>: In member function 'void AllDer::foo()': <source>:10:21: error: 'Base' is an ambiguous base …

1
クラス内の隣接するメンバーの重複を防ぐものは何ですか?
次の3つを検討してくださいstruct。 class blub { int i; char c; blub(const blub&) {} }; class blob { char s; blob(const blob&) {} }; struct bla { blub b0; blob b1; }; intが4バイトである一般的なプラットフォームでは、サイズ、配置、およびパディングの合計1は次のとおりです。 struct size alignment padding -------- ------ ----------- --------- blub 8 4 3 blob 1 1 0 bla 12 4 6 …

1
Haskellで評価される関数a->()にはどのような規則がありますか?
タイトルが言うように:評価されるユニットを返すHaskell関数にはどのような保証がありますか?そのような場合、いかなる種類の評価も実行する必要はないと考えられ()ますが、厳密さの明示的な要求が存在しない限り、コンパイラーはそのようなすべての呼び出しを即時値に置き換えることができます。リターン()またはボトム。 私はこれをGHCiで実験しましたが、逆のことが起こっているようです。つまり、そのような関数は評価されているように見えます。非常に原始的な例は f :: a -> () f _ = undefined 評価f 1すると、が存在するためにエラーがスローされるundefinedため、評価が確実に行われます。ただし、評価の深さは明確ではありません。場合によっては、を返す関数へのすべての呼び出しを評価する必要があるほど深くなるように見えることがあり()ます。例: g :: [a] -> () g [] = () g (_:xs) = g xs このコードは、を指定すると無限にループしg (let x = 1:x in x)ます。しかしその後 f :: a -> () f _ = undefined h :: a -> () h _ …

1
C ++ 20での後の実行時の決定に基づいて、異なる暗黙のオブジェクトが存在する可能性はありますか?
この質問は、最新のC ++ 20ドラフトへのP0593の追加に言及しています。 これが私の例です: #include <cstdlib> #include <cstdio> void foo(void *p) { if ( std::getchar() == 'i' ) { *(int *)p = 2; std::printf("%d\n", *(int *)p); } else { *(float *)p = 2; std::printf("%f\n", *(float *)p); } } int main() { void *a = std::malloc( sizeof(int) + sizeof(float) ); if …

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