2011-10-17 6 views
0

私はcppソースファイルで静的関数を実装しようとします。 再定義エラーを取得します。 誰かが私を助けることができますか?どうもありがとう!静的メンバー関数テンプレートを実装する際にC++の問題が再定義エラーになる

DEFINE_MY_STATIC_PTR(B_type) 
DEFINE_MY_STATIC_PTR(A_type) 

- エラー:再定義

struct A_type : B_type 
{} 

#define DEFINE_MY_STATIC_PTR(TYPE)\ 
    template< typename TYPE > \ 
    My_self_deleting* My_static_ptr<TYPE>::my_self_deleting_ptr(TYPE* ptr) \ 
    { return ptr; } 

template<typename TYPE> 
struct My_static_ptr : My_pointer 
{ 
    static My_self_deleting* my_self_deleting_ptr (TYPE*); 
} 

はどのように適切に定義し、この種のを行うには?

すべてのヘルプから、上記のテンプレートを削除する必要があります。使用時には、それぞれのTYPEの実装になります。

#define DEFINE_MY_STATIC_PTR(TYPE)\ 
    My_self_deleting* My_static_ptr<TYPE>::my_self_deleting_ptr(TYPE* ptr) \ 
    { return ptr; } 

DEFINE_MY_STATIC_PTR(B_type) 
      error: too few template-parameter-lists 

このマクロ定義に何かを追加する必要がありますか?

はい、テンプレートを追加<>

#define DEFINE_MY_STATIC_PTR(TYPE)\ 
    template <> 
    My_self_deleting* My_static_ptr<TYPE>::my_self_deleting_ptr(TYPE* ptr) \ 
    { return ptr; } 
+2

あなたはテンプレートメカニズムを理解していますか? – jopasserat

+0

それでも学ぶ... :-) –

+1

そのマクロの背後にある意図は何ですか?テンプレートを意図どおりに使うのはなぜですか? – PlasmaHH

答えて

0

基本的には、テンプレートのメカニズムは、異なるタイプのために同じアルゴリズムを書き換え避けるために使用することができます。
複数のテンプレートを宣言するマクロを追加すると、テンプレートのの再定義が導入されます。

あなたの場合、テンプレートメソッドの唯一の宣言で十分です。あなたのコードは次のようになりますどのようにここにある:

// declaration of struct A_type 
struct A_type : B_type 
{} 

// declaration of template class My_static_ptr, of template parameter TYPE 
template<typename TYPE> 
struct My_static_ptr : My_pointer 
{ 
    // declaration of template method my_self_deleting_ptr, of template parameter TYPE 
    static My_self_deleting* my_self_deleting_ptr (TYPE*); 
} 

// definition of template static method my_self_deleting_ptr, of template parameter TYPE 
template< typename TYPE > 
My_self_deleting* My_static_ptr<TYPE>::my_self_deleting_ptr(TYPE* ptr) \ 
{ return ptr; } 

次に、あなたは、あなたがそれを使用することができるように、具体的なタイプを使用して、テンプレートをインスタンス化する必要があります。

// instantiation of the template for A_type, by creating an object My_static_ptr parameterized with A_type 
My_static_ptr<A_type> myStaticPointer_of_A_type; 
+0

上記の皆さん、ありがとうございました。私の質問に答えてください。 –

1

私は何を完全にわからないんだけど

クラスがなく、クラスがテンプレートであることを確認してください。つまり、テンプレートをインスタンス化するすべての点で定義を表示する必要があるため、実装を定義から分離することは通常できません。だから、一般的なソリューションは、ヘッダにすべてをかけるために、次のようになります。

// header.hpp 
template<typename T> 
struct My_static_ptr : My_pointer 
{ 
    static My_self_deleting * my_self_deleting_ptr(T * p) 
    { 
    return p; 
    } 
}; 

のみ、特定の、特殊な状況で、あなたは明示的テンプレートのインスタンス化の有界集合を提供する代替案を検討することもでき:

// header.hpp 
template<typename T> 
struct My_static_ptr : My_pointer 
{ 
    static My_self_deleting * my_self_deleting_ptr(T * p); 
}; 

// implementation.cpp 
template<typename T> My_self_deleting * My_static_ptr<T>::my_self_deleting_ptr(T * p) 
{ 
    return p; 
} 
// Only the following specializations are usable in your entire program! 
template struct My_static_ptr<int>; 
template struct My_static_ptr<double>; 
template struct My_static_ptr<Foo>; 
0

なぜこの特定のエラーが発生するのかについては、コンパイラが(この場合はpreproc essor):

DEFINE_MY_STATIC_PTR(B_type) 
DEFINE_MY_STATIC_PTR(A_type) 

それはマクロを適用し、で終わる、マクロ引数のテキスト交換を行います。

template< typename B_type > 
    My_self_deleting* My_static_ptr<B_type>::my_self_deleting_ptr(B_type* ptr) 
    { return ptr; } 

template< typename A_type > 
    My_self_deleting* My_static_ptr<A_type>::my_self_deleting_ptr(A_type* ptr) 
    { return ptr; } 

あなたA_typeB_typeはおそらく、コンパイラのために、その名前の種類を意味するためにいる間それらは単に識別子であるTまたはUです。だから、そのコードはとまったく同じです:

template< typename T > 
    My_self_deleting* My_static_ptr<T>::my_self_deleting_ptr(T* ptr) 
    { return ptr; } 

template< typename T > 
    My_self_deleting* My_static_ptr<T>::my_self_deleting_ptr(T* ptr) 
    { return ptr; } 

そしてそこにあなたが複数の定義を持っている:あなたも、両方の定義場合、二回のエラーで同じ翻訳単位内のクラステンプレートのmy_self_deleting_ptr関数メンバを定義していますまったく同じです。

+0

このケースで私を助けてくれてありがとう。そのすべてが、私にそれを掘り起こす良い知識ベースを与えました。このコードはサードパーティのライブラリから来ており、古いgccコンパイラと一緒に渡すべきです。私が定義の1つをコメントアウトすると、 'MY_Class :: My_static_ptr :: operator =(MY_Class :: A_type *) 'リンクの参照エラーへの未定義の未定義の参照を私に与えるでしょう。それでもコードを見て、より詳細な情報を提供します。 –

関連する問題