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

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

3
C ++ 20の概念:テンプレート引数が複数の概念に該当する場合、どのテンプレートの特殊化が選択されますか?
与えられた: #include <concepts> #include <iostream> template<class T> struct wrapper; template<std::signed_integral T> struct wrapper<T> { wrapper() = default; void print() { std::cout << "signed_integral" << std::endl; } }; template<std::integral T> struct wrapper<T> { wrapper() = default; void print() { std::cout << "integral" << std::endl; } }; int main() { wrapper<int> w; …

3
参照からグローバル変数へのラムダ関数の可変キャプチャの動作の違い
ラムダを使用して、可変キーワードでグローバル変数への参照をキャプチャし、ラムダ関数の値を変更すると、コンパイラによって結果が異なることがわかりました。 #include <stdio.h> #include <functional> int n = 100; std::function<int()> f() { int &m = n; return [m] () mutable -> int { m += 123; return m; }; } int main() { int x = n; int y = f()(); int z = n; printf("%d %d %d\n", x, y, …

1
独自の初期化子での変数の使用
C ++ 20標準草案の[basic.scope.pdecl] / 1には、次の(非規範的)例が注記(プルリクエスト3580のマージ前の部分的な引用、この質問への回答を参照)に含まれていました。 unsigned char x = x; [...] xは、独自の(不定)値で初期化されます。 これは実際にC ++ 20で明確に定義された動作を持っていますか? 一般に、フォームの自己初期化は、初期化が完了する前のの値が不定であるT x = x;ため、未定義の動作をします。不確定な値を評価すると、通常、未定義の動作([basic.indent] / 2)が発生しますが、[basic.indent] /2.3には、不確定な値を持つ左辺値から変数を直接初期化できる特定の例外があります(不確定な値で初期化が発生します) )。xunsigned charunsigned char これだけでは、したがって、未定義の動作を引き起こすが、他のタイプの場合としないT符号なしの狭い文字タイプかそうでないstd::byte、例えばint x = x;。C ++ 17以前にも適用されたこれらの考慮事項は、下部にあるリンクされた質問も参照してください。 ただし、でもunsigned char x = x;、現在のドラフトの[basic.lifetime] / 7は次のように述べています。 同様に、オブジェクトの存続期間が始まる前に[...]その値に依存しないglvalueのプロパティを使用することは明確に定義されています。次の場合、プログラムは未定義の動作をします。 glvalueは、オブジェクトにアクセスするために使用されます。 [...] これはx、例のの値がその存続期間中にのみ使用できることを意味するようです。 [basic.lifetime] / 1は言う: [...] タイプTのオブジェクトの存続期間は、次の場合に始まります。 [...]と 初期化(存在する場合)が完了している(空の初期化を含む)([dcl.init])、 [...] …

3
shared_ptrのdeleterは、カスタムアロケーターによって割り当てられたメモリに格納されていますか?
私が持っていると言うshared_ptrカスタムアロケータでとカスタム削除手段。 削除プログラムを保存する場所について話している標準では何も見つかりません。カスタムアロケータが削除プログラムのメモリに使用されることはなく、そうでないこともありません。 これは指定されていませんか、それとも何か不足していますか?

2
PODタイプであることは、単純な標準レイアウトタイプであることとまったく同じですか?
C ++ 20では、PODの概念は推奨されません。これは、それがささいで標準的なレイアウトであるという意味のない複合特性であるためと考えられます。ただし、C ++ 20ドラフトでのPODの定義は、厳密には「単純なものと標準的なレイアウトの両方」ではありません。実際には: PODクラスは、自明なクラスと標準レイアウトクラスの両方であり、非PODクラス(またはその配列)タイプの非静的データメンバーを持たないクラスです。PODタイプは、スカラータイプ、PODクラス、そのようなタイプの配列、またはこれらのタイプのいずれかのcv修飾バージョンです。 言い換えれば、PODタイプは単純で標準的なレイアウトであるだけでなく、再帰的にもそうです。 この再帰的な要件は冗長ですか?言い換えれば、型が自明で標準的なレイアウトでもある場合、それは自動的に再帰的に自明で標準的なレイアウトでもありますか?答えが「いいえ」の場合、PODに失敗した標準レイアウトの自明なタイプの例は何ですか?


4
戻り時に暗黙的な変換は許可されていません
#include <optional> bool f() { std::optional<int> opt; return opt; } コンパイルしません: 'return': cannot convert from 'std::optional<int>' to 'bool' 参考資料を参考にして説明を探したのですが、大丈夫なので読んでみました。 暗黙的な変換は、あるタイプT1の式がそのタイプを受け入れないが他のタイプT2を受け入れるコンテキストで使用される場合は常に実行されます。特に: T2をパラメーターとして宣言された関数を呼び出すときに、式が引数として使用される場合。 式がT2を期待する演算子でオペランドとして使用される場合。 T2を返す関数のreturnステートメントを含む、T2型の新しいオブジェクトを初期化するとき; 式がswitchステートメントで使用されている場合(T2は整数型)。 式がifステートメントまたはループで使用される場合(T2はブール値)。

1
関数の引数としての{}が曖昧にならないのはなぜですか?
このコードを考えてみましょう: #include <vector> #include <iostream> enum class A { X, Y }; struct Test { Test(const std::vector<double>&, const std::vector<int>& = {}, A = A::X) { std::cout << "vector overload" << std::endl; } Test(const std::vector<double>&, int, A = A::X) { std::cout << "int overload" << std::endl; } }; int main() { …

4
std :: back_inserterでstd :: transformを使用することは有効ですか?
Cppreferenceには、次のサンプルコードがありstd::transformます。 std::vector<std::size_t> ordinals; std::transform(s.begin(), s.end(), std::back_inserter(ordinals), [](unsigned char c) -> std::size_t { return c; }); しかし、それはまた言います: std::transformunary_opまたはの順序どおりの適用は保証されませんbinary_op。関数をシーケンスに順番に適用したり、シーケンスの要素を変更する関数を適用したりするには、を使用しますstd::for_each。 これはおそらく並列実装を可能にするためです。しかし、の3番目のパラメータは、std::transformあるLegacyOutputIteratorため、次の事後条件を有しています++r。 この操作の後rは、増分可能である必要はなく、以前の値のコピーは、r逆参照可能または増分可能である必要がなくなります。 したがって、出力の割り当ては順番に行わなければならないように思えます。それらは単に、アプリケーションunary_opが故障し、一時的な場所に保存されているが、出力に順番にコピーされる可能性があることを意味していますか?それはあなたがしたいことのようには聞こえません。 ほとんどのC ++ライブラリは、実際には並列実行プログラムをまだ実装していませんが、Microsoftは実装しています。私はかなり確信している、これは関連するコードである、と私は考えてそれが呼び出すこのpopulate()機能をするので確実に行うために有効なものではありません出力、のチャンクにレコードイテレータに LegacyOutputIteratorそれのコピーをインクリメントすることによって無効にすることができます。 何が欠けていますか?


2
矢印(->)演算子の優先順位/優先順位が最も低いか、割り当て/組み合わせ割り当ての優先順位が最も低いですか?
JLS: 最も優先順位の低い演算子は、ラムダ式の矢印(->)で、その後に代入演算子が続きます。 どちらの方向に進んだか(優先度の増加、優先度の減少)?-「フォロー済み」とは、割り当てが(矢印演算子に対して)優先度が高いか低いかを意味します。「最低」(矢印)は絶対最低を意味するので、増加すると思います。 私が理解しているように、矢印(->)はこのプリンストン演算子の優先順位表の一番下(つまり、すべての代入演算子の下にあります)にある必要があります。 私の理解は正しいですか? ExamTrayは、矢印の優先順位は少なくとも割り当てと同じであると言っているようです...さらに、矢印の結合性は(割り当てとは異なり)左→右→右であることを明確にしました。矢印の結合性に関するJLSの引用は見つかりませんでした。 私はいつも、割り当ての優先順位は主に理由により最低だと思っていました。

2
変数の初期化を飛び越えるのは不適切な形式ですか、それとも未定義の動作を引き起こしますか?
このコードを考えてみましょう: void foo() { goto bar; int x = 0; bar: ; } へのジャンプが変数の初期化をバイパスするため、GCCとClang はそれを拒否しbar:ます。MSVCはまったく文句を言いません(xafter を使用bar:すると警告が表示されます)。 同じことをaで行うことができますswitch: void foo() { switch (0) { int x = 0; case 0: ; } } 3つのコンパイラすべてがエラーを出力するようになりました。 これらのスニペットの形式は不適切ですか?または、それらはUBを引き起こしますか? 以前はどちらも形式が正しくないと思っていましたが、標準の魅力的な部分を見つけることができません。[stmt.goto]は、このことについて何も言われ、どちらもしないん[stmt.select] 。

1
C ++標準がファイルを処理する方法を模索するのはなぜですか?
C ++は、streamoffタイプを使用して(ファイル)ストリーム内のオフセットを表し、[stream.types]で次のように定義されます。 using streamoff = implementation-defined ; タイプstreamoffは、オペレーティングシステムの最大可能ファイルサイズを表すのに十分なサイズの、署名された基本的な整数型の1つの同義語です。287) 287)通常は長いです。 これは、(long32ビット幅しかない可能性があるを使用するのとは対照的に)大きなファイル内をシークできるため、理にかなっています。 [filebuf.virtuals]はbasic_filebuf、ファイル内でシークする関数を次のように定義します。 pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override; off_typestreamoffはと同等です。[iostreams.limits.pos]を参照してください。ただし、標準は、関数の効果を説明し続けます。私は最後の文にイライラしていますfseek。 効果:レッツをwidth示しますa_codecvt.encoding()。is_open() == false、またはの場合、off != 0 && width <= 0位置決め操作は失敗します。それ以外の場合、way != basic_ios::curまたはoff != 0、および最後の操作が出力された場合は、出力シーケンスを更新し、シフト解除シーケンスを書き込みます。次は、新しい位置をシーク:場合はwidth > 0、呼び出しfseek(file, width * off, whence)、そうでない場合は呼び出しますfseek(file, 0, whence)。 fseeklongパラメータを受け入れます。off_typeとstreamoff定義されている場合long long(標準で推奨されているとおり)、これはlong呼び出し時にへのダウンコンバージョンにfseek(file, width * off, …

1
Clangは、クラステンプレートのネストされたクラスが特殊化によってのみ定義されているコードを拒否することは正しいですか?
次のクラステンプレートがあるとします。 template<typename T> struct Outer { struct Inner; auto f(Inner) -> void; }; のInner専門化ごとに個別に定義しますOuter。 template<> struct Outer<int>::Inner {}; template<> struct Outer<double>::Inner {}; 次にf、すべての特殊化についてメンバー関数を1回定義しますOuter。 auto Outer<T>::f(Inner) -> void { } しかしClang(9.0.0)は不平を言います: error: variable has incomplete type 'Outer::Inner' auto Outer<T>::f(Inner) -> void ^ Inner他のすべての特殊化の定義も提供することにより、コンパイラエラーを回避できますOuter。 template<typename T> struct Outer<T>::Inner {}; または、f専門化ごとに個別に定義することにより: template<> auto …

1
sizeof(enum)はsizeof(std :: underlying_type <Enum> :: type)と異なることがありますか?
最近、次の例のコードレビューで登場しました。 enum class A : uint8_t { VAL1, VAL2 }; ... std::vector&lt;A&gt; vOfA; // Assume this is sized and full of some stuff. std::memcpy(wire_buffer, vOfA.data(), vOfA.size() * sizeof(A)); のsizeof(std::underlying_type&lt;A&gt;::type)代わりに使用する必要がありsizeof(A)ます。これらが異なる可能性はありますか?誰かがこれを保証する標準の見積もりを持っていますか?

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