6

次の変数からのリンケージについていくつか質問があります。C++03の7.1.1/7の例とコンパイラー(Comeau、Clang、GCC)の実験により、次の種類のリンケージにたどり着きました。

  1. 最初staticに、次にextern

    static int a; // (a)
    extern int a; // (b) valid, 'a' still internal
    

    セクション3.5によると、私には明らかです。(a)内部リンクを意味します。また、(b)は、名前「a」が静的であると宣言されているため((a)によって)、内部リンケージも意味します。

  2. 最初externに、次にstatic

    extern int b; // (c)
    static int b; // (d) invalid!
    

    まず、(c)は外部リンケージを意味します。ただし、(d)は、名前「b」が(d)によって静的であると宣言されているため、内部リンクを意味します。暗黙のリンケージが一貫していないため、7.1.1/7によるとこれは無効です。

  3. 最初constに、次にextern

    const double pi1 = 3.14; // (e)
    extern const double pi1; // (f) valid and 'pi1' is internal
    

    まず、(e)は内部リンケージを意味します。これは、constであり、明示的な外部リンケージを宣言しておらず、以前は外部リンケージを暗示していなかったためです。また、(f)externリンケージを意味し、エラーになるはずです。これは、externという名前を明示的に宣言しているためですが、コンパイラーはそれを内部に保持します。なぜそうなのか? それが私の質問です。

  4. 最初externに、次にconst

    extern const double pi2; // (g)
    const double pi2 = 3.14; // (h) valid and 'pi2' is external
    

    ここで、(g)は、externを明示的に宣言したため、外部リンケージを意味します。また、(h)は、(g)externを明示的に宣言しているため、外部リンケージも意味します。


次のテンプレートを使用して、3と4のリンケージを実験的に見つけました(2番目の引数は外部リンケージが必要です)

template<typename T, T&> struct ensure { };

ensure<const double, pi1> e1; // failed
ensure<const double, pi2> e2; // succeeded

要約:チャールズベイリーとの話し合いは非常に実り多いものであることが判明し3.5/3、重要な箇条書きが

名前空間スコープ(3.3.5)を持つ名前は、

  • constとして明示的に宣言されており、externとして明示的に宣言されておらず、外部リンケージを持つように以前に宣言されていないオブジェクトまたは参照。

ポイントを見ると(f)、以下に示すように、2つの解釈は異なる結論に達します。

  1. 宣言されているが、pi1宣言されている最初の解釈ノート。したがって、変数には外部リンケージがあります。constextern

  2. 2番目の解釈は、「宣言された」の両方の出現を解釈して、同じ宣言を参照します。このように、それは宣言されているが、ではconstないextern constことを意味します。(e)は宣言されており、宣言されconstていないことに注意してください。extern constしたがって、pi1内部リンクを提供します。

さて、どのような解釈が正しいのでしょうか?その言葉遣いからは判断できませんが、コンパイラーはこれを2番目の方法で解釈しているようです。特に、最初の解釈を行う場合、名前が宣言され、以前に外部リンケージを使用して明示的に宣言3.5/3されていない有効なシナリオがないため、の最後に引用された部分は不要になります。constextern

4

3 に答える 3

4
const double pi1 = 3.14; // (e)
extern const double pi1; // (f) valid and 'pi1' is internal

私の解釈は次のとおりです。名前のリンクを検討するときは、以前の宣言と、解析のこの時点で解釈されている宣言を検討します。static int a; extern int a;これがOKである理由ですが、そうでextern int b; static int b;はありません。

最初の宣言に遭遇すると、それpi1は明示的に宣言されていますconstが、明示的に宣言されexternておらず、外部リンケージを持つように以前に宣言されていません。これは3.5/2のオプションの1つと一致するため、pi1内部リンクがあります。

2番目の宣言に遭遇すると、明示的に宣言されているが明示的に宣言されておらず、[...blah...]でもないpi1オブジェクトの名前が尋ねられます。それはポイント(e)でそのように宣言されたからだと私は主張します。確かに、それはどこでもそのように宣言されていませんが、同じように、どこでも宣言されていなくても、宣言を検討しているときに宣言されたオブジェクトの名前でした。これは、私にとって、宣言(f)が宣言(e)とは異なるリンクを意味しないことを意味します。constexternastaticextern int a;static

于 2010-08-22T00:55:37.723 に答える
0

#3では、分析に誤りがあったと思います。私の知る限り、constリンケージについては何も意味しません。コンパイラがリンケージを内部化するという結論にどのように到達しているかはわかりません。ほとんどのコンパイラは(最適化として)const変数へのすべての参照を初期化された値に置き換えるため、コードにシンボルがまったく表示されない場合があります。

そして、あなたがそうしなかったとしても、#1から、内部リンケージを持つ何かがその後externキーワードで宣言された場合、それは内部リンケージのままであることが明らかです。だから私はあなたがエラーを期待する理由がわかりません。

そして、const暗黙の内部リンケージの場合、#2と同じ理由で#4はエラーになるはずです。

于 2010-08-21T21:12:08.683 に答える
0

(e)と(f)の両方を同じ名前空間スコープに含めることは、§7.1.1/7「特定のエンティティの連続する宣言によって暗示されるリンクは同意するものとします。」によって単に無効になります。

このルールには診断が必要です。

However, at least Comeau Online does not diagnose the violation.

Cheers & hth.,

EDIT: He he, I looked up DR 426, as mentioned in another answer here, and it seems those who drafted the proposed resolution, making it UB instead of diagnosable, were not aware of §7.1.1/7. I'm not going to comment on the issue or even raise it in comp.std.c++ because I found the standardization work to be far too political and nonsensical (mumbo-jumbo arguments) for me. But either way, the code's not valid.

于 2010-10-29T06:02:36.343 に答える