2016-05-17 5 views
7

this presentation 00:19:00頃、Andrei Alexandrescuは彼のSCOPE_EXITマクロの実装について説明します。ここで__COUNTER__はODR違反を引き起こしますか?

#define ANONYMOUS_VARIABLE(str) \ 
    CONCATENATE(str, __COUNTER__) 

namespace detail { 
    enum class ScopeGuardOnExit {}; 
    template <typename Fun> 
    ScopeGuard<Fun> 
    operator+(ScopeGuardOnExit, Fun&& fn) { 
     return ScopeGuard<Fun>(std::forward<Fun>(fn)); 
    } 
} 

#define SCOPE_EXIT \ 
    auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \ 
    = ::detail::ScopeGuardOnExit() + [&]() 

はこれまでのところ、非常によく知られている(彼も、これは古い帽子であることを彼のスライドで述べている):彼は破壊にラムダを実行スタック上ScopeGuardオブジェクトを作成します。使い方は次のようになります。

void foo() 
{ 
    SCOPE_EXIT{ printf("foo exits"); }; 
} 

しかし1時04分00秒で、チャンドラーCarruthは、インライン関数で使用する場合__COUNTER__マクロのこの用法は、ODR違反を引き起こす「匿名」の名前を作成することを主張しています。これは本当ですか?このマクロは、型名などではなく、ローカル変数名の作成にのみ使用されるため、ODR違反の原因となるのはなぜですか?

答えて

8

インライン関数が2つの異なる翻訳単位に含まれるヘッダーにあり、カウンタの値がそれぞれ異なる値にあるとします。

次に、変数の名前が異なるインライン関数の定義が2つあります。これはODR違反です。すべての定義に同じトークンシーケンスを使用する必要があります。

(それが何か問題を起こした場合は、実際に、私は非常に驚かれると思いますが。)

+0

私はちょうどそれが機能自体の定義についてですことを理解することが私にしばらく時間がかかった、同じ結論に達しました。しかし、たとえそれがちょっと変わった変数名であったとしても、これは意味があります。私は誰もこれが問題を引き起こさないことを願っていますね...多分LINEマクロはここでより良い選択でしょうか? – Horstling

+0

はい、1行に複数のものを宣言しない限り、そうです。 (または、 '#line'をつぶっています。) –

関連する問題