5

私の元のクラス構造は次のようになりました。

//def.h
namespace A
{
   struct X {};
}

必要に応じて宣言を転送します。

//file that needs forward declarations
namespace A { struct X; }

いくつかのリファクタリングの後X、別の名前空間に移動されましたが、古いコードを維持するために「動作する」usingディレクティブが使用されました。

//def.h
namespace B
{
   struct X {};
}
namespace A
{
   using ::B::X;
}

これで、古い構文を維持したまま同じクラスにアクセスできますA::Xが、前方宣言によりエラーが発生します。2番目の問題は、表示されるエラーメッセージが前方宣言の場所を示しておらず、前方宣言の検索/置換に時間がかかることです。

今のところ私は問題を修正しました(難しい方法)。

この状況に対処するための最良のアプローチは何ですか?

IMOはusing存在すべきではなく、使用するすべてのコードをXリファクタリングして新しい名前空間に対応する必要があります(これは1つの解決策です)が、残念ながらこれはオプションではありません。

実際のコードはもっと複雑です。これは単純化された例です。

4

2 に答える 2

4

これは、既存のコードをリファクタリングするというよりも、新しいコードに関するものだと認識していますが、そのような場合に呼び出される特別なヘッダーを使用するのが好きX_fwd.hppです。

// X_def.hpp
namespace B
{
   struct X {};
}
namespace A
{
   // NOT: using namespace B; // does not participate in ADL!      
   typedef ::B::X X;  // OR: using ::B::X;
}

// X_fwd.hpp
namespace A { struct X; }

// some file needing declaration of X
#include <X_fwd.hpp>

これにより、前方宣言を見つけるのがはるかに簡単になり、変更が 1 か所だけに分離されるため (DRY...)、事後にそれらを変更することも容易になります。

注1typedef :知る限り、Peter Woodのaの回答とあなたのusing宣言の使用の間に技術的な違いはありません。これらはArgument-Dependent-Lookupによって無視されるため、usingディレクティブが問題を引き起こす可能性があることに注意してください。さらに悪いことに、新しい名前空間をもうプルしていないため、コードの一部が間違った関数オーバーロードを暗黙のうちに呼び出すことさえあります!using namespace B;B

注2:質問へのコメントで、Ideoneの例が示されました。これは、名前空間内の名前検索に関する微妙な点をうまく示しています。ドラフトStandard、セクション3.4.3.2 Namespace members [namespace.qual]、節 2から引用するには

名前空間 X と名前 m の場合、名前空間で修飾されたルックアップ セット S(X, m) は次のように定義されます。 (7.3.1)。S'(X, m) が空でない場合、S(X, m) は S'(X, m) です。それ以外の場合、S(X, m) は、X の using ディレクティブによって指定されたすべての名前空間 Ni とそのインライン名前空間セットの S(Ni, m) の和集合です。

これは、次のトリッキーなあいまいさを説明しています

namespace A
{
    struct X1{};
    struct X2{};
}

namespace B
{
    using A::X1;    // OK: lookup-set is both namespace A and B, and a single unique name is found (at this point!)
    struct X1;      // OK: lookup-set is namespace B, and a single unique name is found

    struct X2;      // OK: lookup-set is namespace B, and a single unique name is found
    using A::X2;    // error: lookup-set is both namespace A and B, and no unique name is found (at this point!)
}

したがって、名前空間内に同じ名前を持つ直接宣言と using 宣言の両方を持つことの有効性は、順序に依存します。したがって、fwd ヘッダー ファイル内の単一の宣言の利便性。

于 2013-01-09T13:28:05.480 に答える
1

最善の方法は、コードを修正することです。

次の 2 つの手順で実行できます。

  1. すべての前方宣言を修正
  2. 削除するusing ::B::X;
于 2013-01-09T13:06:12.637 に答える