5

注: この質問は tinyxml に大まかに関連しているだけですが、そのような詳細を含めると、概念をよりよく説明するのに役立つ場合があります。

親 XML ノードの子を反復処理し、子要素の値を取得して、その子要素の値をベクターにプッシュする関数テンプレートを作成しました。

「値を取得する」部分も関数テンプレートとして記述されています。

すなわち

template <typename Type>
Type getXmlCollectionItem(
    const char* elementName, TiXmlNode* child, TiXmlNode* parent);

std::string やその他のカスタム オブジェクトなど、さまざまなタイプの子要素の値を返すために、検索部分の特殊化があります。

すなわち

template <>
std::string getXmlCollectionItem<std::string>(
    const char* elementName, TiXmlNode* child, TiXmlNode* parent);

template <>
MyObject getXmlCollectionItem<MyObject>(
    const char* elementName, TiXmlNode* child, TiXmlNode* parent);

これはすべて完全にうまく機能しますが、tinyxml ファイルを扱うときに共有関数ライブラリにあると非常に便利だと思いました。

質問:namespace UtilityFunctionsのような特定のオブジェクト型の知識を持たない1 つの名前空間で関数テンプレートを宣言し、特定のオブジェクト型'MyObject'の知識を持つ他の名前空間でその関数テンプレートの特殊化を宣言および定義することは可能ですか?のような'MyObject'

私の推測では、それは不可能ですが、共通の関数テンプレートを持つという概念は、私が探している機能に近づく別の方法があるのに十分役立つように思えます...

用語の誤りや説明が不明確な場合はお詫び申し上げます。私はこのトピックについて多くの調査を行いましたが (同じ名前空間内で関数テンプレートの特殊化を機能させるため)、まだ決定的な答えは見つかりませんでした。

4

2 に答える 2

5

ある名前空間で、別の名前空間で定義されたテンプレートの特殊化を記述することはできません(それはそのテンプレートの特殊化ではないため、別の名前空間で定義されていると別のテンプレートになります)。

ただし、テンプレートが最初に定義された名前空間を拡張して、完全に別のソース ファイルに特殊化を記述してもまったく問題ありません。

したがって、ここでできないことは次のとおりです。

namespace A { namespace B {
  template <typename T> int foo(T) {throw 1;}
}}

template <> int A::B::foo(int) {throw 0;}

上記の適切なエラー メッセージは、http://www.comeaucomputing.com/tryitout/で確認できます。

"ComeauTest.c", line 5: error: the initial explicit specialization of function
          "A::B::foo(T) [with T=int]" must be declared in the namespace
          containing the template
  template <> int A::B::foo(int) {throw 0;} 
                        ^

できることは次のとおりです。

namespace A { namespace B {
  template <typename T> int foo(T) {throw 1;}
}}

namespace A { namespace B {
  template <> int foo(int) {throw 0;}
}}

それが問題になる理由はありますか?

また、読み取り中のオブジェクトに関連付けられた関数 (メンバーまたはフリー関数のいずれか) に作業を委譲する場合、その関数が ADL を介して検出され、呼び出されることに依存できます。つまり、上記のような特殊化の量を最小限に抑えることができるはずです。

次に例を示します。

namespace A { namespace B {
  template <typename T> int bar(T t) {return 0;}
  template <typename T> int foo(T t) {return bar(t);}
}}

namespace C {
  struct Bah {};
  int bar(Bah&) {return 1;}
}


int main(int argc,char** argv) 
{
  C::Bah bah;

  std::cout << A::B::foo(0) << std::endl;
  std::cout << A::B::foo(bah) << std::endl;
}

例を追加するために編集

于 2012-01-18T15:28:37.697 に答える
1

ここでのポイントは、「テンプレートのすべての宣言は、他の名前付きエンティティの繰り返し宣言と同様に、同じ名前空間に配置する必要がある」ことです。

別の名前空間での宣言/定義は無効です。詳細については、FAQの 12 番目のポイントを参照してください。

于 2012-01-18T15:41:02.447 に答える