C++ 属性

C++11 では、gnu __attribute__ などの標準化された機能への方法として属性が追加されました。 msvc の __declspec .

非標準属性の動作は C++17 でのみ解決されましたが、言語は名前空間を使用して標準属性と非標準属性を規定しています。残念なことに、2018 年現在、GCC も MSVC も、移植可能な C++ 標準構文を介してベンダー固有の属性を提供していません。

ほとんどの標準属性は、C++14 および 17 で追加されました。listoncppreference を見つけることができます。

C++11 が登場する前のある時点で、C++ 標準ドラフトは [[override]] を定義しました。 そして [[final]] 属性。これらの機能は後で文脈キーワード override に変換されました および final .最初の提案では、属性を使用してデフォルトおよび削除されたメソッドを可能にすることさえ提案していました。これらの機能は =default として知られています と =delete .

それ以来、言語機能を C++ に追加するときは、その機能がキーワードまたは属性によってより適切に提供されるかどうかという問題を尋ね、回答する必要があります.

最近、現在受け入れられている [[no_unique_address]] に登場しました 現在議論されている [[move_relocates]] (私の理解の範囲では、これは破壊的な動き、場合によっては優れたパフォーマンスの最適化に似ています)。

体系的に、委員会のメンバーは次のように指摘します。 」。もう 1 つは「実は、属性はプログラムのセマンティックを変更するべきではありません」と追加します。 」。より正確には、

特定の属性のすべてのインスタンスを無視して有効なプログラムをコンパイルすると、元のプログラムが正しく実装されるはずです

出典: p0840r0

これは不文律のようなもので、実際には標準のどこにもありませんが、最初の属性提案で次の引用を見つけました:

これが属性の良い候補となるのは、これらの属性で実行されるコードは、属性が無視された場合でも同じように実行されるということです。ただし、型チェックは少なくなります。

非標準属性の場合、これは非常に理にかなっています。移植性のないコードやベンダー拡張の暗い過去は忘れるべきです。したがって、標準外の属性を単純にスキップすることは、非常に便利で望ましいことです。

では、標準属性はどうでしょうか。コンパイラはそれらも自由に無視できます。

[[fallthrough]] を使用するとしましょう 属性があり、0-warning ポリシーがある場合 (たとえば、-WError でコンパイルするとします)、コンパイラは自由に警告を発してビルドを失敗させることができます。

[[no_unique_address]]の場合 ,sizeof 属性が無視されるかどうかによって異なる結果が返される場合があり、それによってプログラムのセマンティックに影響を与えることができます。どちらも、委員会が必ずしも独自の規則に従うわけではないことを示していますが、最も重要なことは、その属性が無視できるということは、開発者の意図と一致していません.

ベンダが部分的かつ独断的な方法で標準を実装することが多いことを人々が期待することを学んだとしても、彼らは単にキックのため、またはコードに芸術的なクリスマスの飾りを与えるためだけに属性を振りかけることはおそらくないでしょう。誰かが関数のマーク付けに苦労した場合[[nodiscard]] 、彼らはおそらく関数の結果をチェックしたいのです。戻り値をチェックしないと、何らかの理由で重大なエラーが発生する可能性があります。ロケットが爆発し、患者が死ぬ。

既存の属性についても、実装可能性の懸念はありません。ハードウェア要件を課さないため、すべてのハードウェアに実装できます。 [[caries_dependencies]] のハードウェアがいくつかあると思います 意味はありませんが、そのようなハードウェアでは std::memory_order も意味がなく、要点が無意味になります。

私は何人かの委員会メンバーに、しつこい質問をしようとしました:なぜ?属性にセマンティックな意味を持たせる必要がないのはなぜですか?

私が得た答えは、理由でした。

そして、その背後にあるより多くの論理的根拠を見つけるのは困難でした.そして、原則として、根拠のない非常に面倒なことは何もありません.

私が与えられた理由は、強力なガイドラインがない場合、委員会が属性を使用してより多くのキーワードを言語に押し込む可能性があるためです。属性を追加する方がキーワードを追加するよりも簡単だからです。そして、属性がすべてであることは、言語を不敬虔な属性のスープにするかもしれません.

それは確かに正当な懸念です。しかし、委員会は本当にそれ自体に規則を課す必要があるのでしょうか。彼らは依然として、標準に含まれるすべての標準属性に投票する必要があり、この奇妙な不文律の存在の有無にかかわらず、属性の関連性を調査する必要があります.

属性をキーワードにするべきかどうか、または属性に意味的な意味を持たせる必要があるかどうかについて、一般的な良い答えはないと思います。

代わりに、その質問には属性ごとに回答する必要があります.Should alignas キーワードですか?そうでないかもしれない。 [[fallthrough]] すべき おそらく。これは、キーワードを属性として押し込んで、ユーザーのコードを壊さないようにする良い例です。

最終的に、その種の考察は非常に主観的なものですが、一見恣意的なルールを導入することで設計プロセスが容易になるとは思えません。おそらくその逆です。

代わりに、提案された各標準属性 (またはキーワード) は、それ自体のメリットを精査する必要があり、おそらく、それらを無視することが理にかなっている属性を見つけるでしょう. /P>

これは口論のように聞こえるかもしれませんが、ある程度はそうです。ただし、リフレクションのコンテキストでは問題になる場合があります。

属性の反映

属性に関する考察は、考察の最も重要な側面であると思います。クラスをシリアライズしたい場合、リフレクションを使用してすべてのメンバーにアクセスすると、シリアライズしたくないメンバーを除外する必要がある場合があります。これを行う 1 つの方法は、型システムを (ab) 使用することですが、より良いシステムはおそらく、関連するメンバーにタグを付けるために属性を使用することです。これにより、驚くべきシリアライゼーション、RCP、および ORM ライブラリへの扉が開かれる可能性があります (...おそらく ORM を使用するべきではありませんが!)

ほとんどの人はそのような機能の価値を理解しているようですが、デコレータと呼ばれる別の構文を追加した方がよいと主張する人もいます。 これは本質的に属性と同じものであり、属性と同じ場所で使用されますが、「属性は無視できるべきである」という議論から除外される新しい構文を使用します.

私には、これは本当に意味がありません。まず、ユーザーがリフレクションによって属性にセマンティックな意味を与えることを選択した場合、それはコンパイラーではなくユーザーの選択であるため、移植性の問題は適用されません。そしてもちろん、この機能は、フレームワーク固有の動作やイディオムを開発するために使用される可能性があり、使用される可能性があります。しかし、それは存在するニーズであり、今日では複雑なマクロまたはコード生成 (多くの場合両方 (Qt)) によってエミュレートされています。

新しい構文を追加して、専門家以外には失われる哲学的な微妙さに別の名前を付けることは、ほぼ確実に言語に価値を追加しません。もちろん、newsyntax が議論されている間、遅延が追加されます。 C++ のトークンが不足しています。

たとえば、次のうちどれが最も読みやすいと思いますか?

[[deprecated]] QSignal<void> f();
[[deprecated]] @@qt::signal@@ void f();
[[deprecated]] [[qt::signal]] void f();

属性を反映することには、他にも課題があります。属性は、トークン スープとして現在定義されているパラメーターを使用できます。ヘム、Imean トークン シーケンス 申し訳ありません。バランスのとれたトークン スープ シーケンス。ツールとコンパイラにとって、どの Iguess が完全に理にかなっているのか。しかし、熟考に関してはかなり無意味です。

この問題には解決策があると思います。つまり、reflectable-attributes を使用前にソースで宣言し、リテラルと constexptr を許可することです。 任意のトークンではなく、パラメータとして。

詳細については、GitHub に記載しています。これは提案ではなく、少なくとも「属性は無視すべきである」というマントラが存在する間は提案するつもりはありません。

cor3ntin/CPPProposals

最終的に、属性にはさまざまな用途があります:

    <リ>

    最適化と診断のためのコンパイラ ディレクティブ

    <リ>

    外部ツールの説明とメタデータ

    <リ>

    コードインジェクションのリフレクションの両方を使用したフィルタリングと装飾 (コードインジェクションにより、Python が提供する同名の機能と同様の表現力を持つ本格的なデコレーターとして属性を使用できるようになります)

    <リ>

    契約 ( [[expects:]][[ensures:]] );ただし、これらの構文は十分に異なっているため、属性としての資格があるかどうかはわかりません.

しかし、現状では、属性が犯罪的に十分に活用されておらず、機能していないように感じます.

表示したい属性は何ですか?