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

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

5
ユーザー定義リテラルのすべての「通常の」使用は未定義の動作ですか?
ユーザー定義のリテラルはアンダースコアで始める必要があります。 これは多かれ少なかれ一般的によく知られているルールであり、ユーザーのリテラルについて話しているすべての素人のサイトで見つけることができます。それは私(そしておそらく他の人たち?)が「なんてでたらめな」ベースで以来、露骨に無視してきたルールでもあります。もちろん、これは厳密には正しくありません。厳密に言うと、これは予約済み識別子を使用するため、未定義の動作を呼び出します(実際には、コンパイラから肩をすくめるほどではありません)。 それで、私が標準のその(私の意見では役に立たない)部分を故意に無視し続けるべきかどうかを考えて、私は実際に何が書かれているかを調べることにしました。なぜなら、誰もが知っていることが重要なのです。重要なのは、標準で書かれていることです。 [over.literal]「一部の」リテラル接尾辞識別子は予約されており、にリンクして[usrlit.suffix]いることを示しています。後者は、アンダースコアで始まるものを除いて、すべて予約されていると述べています。わかりました。これは、私たちがすでに知っていて、明示的に書かれた(または逆に書かれた)こととほぼ同じです。 また、明白だが厄介なことを示唆するメモが[over.literal]含まれています。 上記の制約を除いて、それらは通常の名前空間スコープ関数と関数テンプレートです まあ、確かにそうです。彼らがそうではないと言っているところはどこにもないので、あなたは彼らがそうであると他に何を期待するでしょう。 しかし、ちょっと待ってください。グローバル名前空間で[lex.name]アンダースコアで始まる各識別子は予約されていることを明示的に述べています。 現在、リテラル演算子は通常、明示的に名前空間に入れない限り(これはだれもしないと思います!?)、大部分はグローバル名前空間にあります。したがって、名前はアンダースコアで始まる必要があり、予約されています。特別な例外についての言及はありません。したがって、すべての名前(下線あり、またはなし)は予約済みの名前です。 「通常の」使用法(アンダースコアかどうかにかかわらず)が予約名を使用しているため、ユーザー定義のリテラルを名前空間に入れることが本当に期待されていますか?

2
多次元配列の空の文字列リテラルがnullポインターに減衰するのはなぜですか?
いくつかの文字列リテラルで初期化された多次元C文字列配列を定義したいと思います。ではC Iは、次の操作を行います: #include <stdio.h> const char *strArr[2][1] = { {"foo"}, {""}}; int main(void) { printf("%p\t%p\n", strArr[0][0], strArr[1][0]); return 0; } gcc -std=c18 -pedantic test.c結果をコンパイルして実行すると、次のようになります。 $ ./a.out 0x55d95410f004 0x55d95410f008 予想どおり、空の文字列リテラルはstrArr[1][0]有効なポインタに減衰します。 しかし、私は同じコードを試してみてくださいC ++: #include <cstdio> const char *strArr[2][1] = { {"foo"}, {""}}; int main(void) { printf("%p\t%p\n", strArr[0][0], strArr[1][0]); return 0; } g++ …

1
using宣言でユーザー定義の変換テンプレートを参照することはできますか?
class Bから継承するクラスAでは、次のように、using宣言を使用してのメンバーAをB、さらにはテンプレートに含めることができます。 struct A { template <typename T> void foo(); }; struct B : private A { using A::foo; }; しかし、それは変換テンプレートに対して行うことができますか? struct A { template <typename T> operator T(); }; struct B : private A { using A::operator /* ??? */; }; テンプレートを名前で参照する方法はないようですが、間違っていることが判明するか、説明が必要です。

1
コンパイラは、暗黙的に宣言された仮想デストラクタの実装を単一の個別の翻訳単位に配置できますか?
次のコードはVisual Studio(2017と2019の両方で/permissive-)でコンパイルおよびリンクしますが、gccまたはでコンパイルしませんclang。 foo.h #include <memory> struct Base { virtual ~Base() = default; // (1) }; struct Foo : public Base { Foo(); // (2) struct Bar; std::unique_ptr<Bar> bar_; }; foo.cpp #include "foo.h" struct Foo::Bar {}; // (3) Foo::Foo() = default; main.cpp #include "foo.h" int main() { auto foo = std::make_unique<Foo>(); …

3
標準Cでは `(i)= 1`は違法ですか?
私はこの標準に従っているCコンパイラを書いており、次のようなステートメントを解析した場合: int i; (i) = 1; 私のコンパイラ(i)は、それが右辺値であり、割り当て可能であってはならないことを指摘するエラーを報告します。 コードとルールを確認したところ、次のことがわかりました:代入式のセマンティクス: 代入演算子は、左オペランドとして変更可能な左辺値を持つものとします。 割り当て式は、割り当て後に左のオペランドの値を持っていますが、左辺値ではありません。 私の場合は、2つの代入式があります (i) = 1し、i括弧インチ したがって、これは(i)右辺値である必要があります。 だから私の質問です:(i) = 1このC標準では 違法ですか?
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.