web-dev-qa-db-ja.com

ヘッダーファイルの匿名名前空間の使用

SO今日、ヘッダーファイルで匿名の名前空間を使用してはならないことを主張しました。通常これは正しいですが、標準ライブラリの1つがヘッダーで匿名の名前空間を使用していると誰かが教えてくれたことを覚えていますある種の初期化を実行するファイル。

私は正しく覚えていますか?誰かが詳細を記入できますか?

48
David Norman

ヘッダーの名前のない名前空間が役立つ唯一の状況は、コードをヘッダーファイルのみとして配布する場合です。たとえば、Boostの大規模なスタンドアロンサブセットは純粋なヘッダーです。

別の回答で述べられているタプルのトークンignoreは、1つの例、_1_2など。バインドプレースホルダは他のものです。

25
James Hopkin

ヘッダーファイルに匿名の名前空間を挿入しても意味がありません。私は標準とlibstdc ++ヘッダーをgrepしましたが、Tupleヘッダー(C++ 1xのもの)に1つ以外の匿名の名前空間は見つかりませんでした:

  // A class (and instance) which can be used in 'tie' when an element
  // of a Tuple is not required
  struct _Swallow_assign
  {
    template<class _Tp>
      _Swallow_assign&
      operator=(const _Tp&)
      { return *this; }
  };

  // TODO: Put this in some kind of shared file.
  namespace
  {
    _Swallow_assign ignore;
  }; // anonymous namespace

これはあなたができるようにするためです

std::tie(a, std::ignore, b) = some_Tuple;

some_Tupleの要素には左側の変数が割り当てられます( here を参照)。同様の手法が this イテレータに使用されます。 2番目の要素は無視されます。

しかし、彼らが言うように、それは.cppファイルに入れられ、1つのインスタンスはすべてのユーザーによって共有されるべきです。彼らはそれを次のようにヘッダーに宣言します:

extern _Swallow_assign ignore;

さまざまな翻訳単位で変数のデフォルト値を提供するために使用されるのを見てきました。ただし、名前が衝突した場合、予期しない動作が発生する可能性があります。

a.hpp

namespace
{
    const char name[] = "default";
}
// This macro will hide the anonymous variable "name"
#define SET_NAME(newname) \
static const char name[] = newname;

b.cpp

#include "a.hpp"
SET_NAME("file b") // name is "file b" in this translation unit

c.cpp

#include "a.hpp"
SET_NAME("file c") // name is "file c" in this translation unit

d.cpp

#include "a.hpp"
// name is "default" in this translation unit

e.cpp

#include "a.hpp"
static const char name[] = "unintended";
// accidently hiding anonymous name
6
Jacqui Gurto

ヘッダーで匿名の名前空間を使用することによるプラスのメリットは実際にはありません。同じシンボル宣言が原因で発生する混乱は、本質的に、そのヘッダーを含むコンパイルユニットでの別のことは、時期尚早で痛々しいほど脱毛するための保証された方法になることを意味します。

2
Jon Trauntvein

初期化の場合、それはおそらくiostreamsヘッダー(istreamiosなど)です。

0
Max Lybbert