2012-10-09 5 views
7

私はC + +で特定のテンプレート友情の質問があります。ブックC++入門で は、特定のテンプレートの友情は次のように書かれている:特定のテンプレートC++での友情

template <class T> class Foo3; 
template <class T> void templ_fcn3(const T&); 
template <class Type> class Bar { 
    // each instantiation of Bar grants access to the 
    // version of Foo3 or templ_fcn3 instantiated with the same type 
    friend class Foo3<Type>; 
    friend void templ_fcn3<Type>(const Type&); 
    // ... 
}; 

特別な点は、友人文のクラス、または関数名の後に

<Type> 

があるということです。

しかし、実際には、私が書く場合、これは:

template <class Type> class T_CheckPointer; 
template <class T> T_CheckPointer<T> operator+(const T_CheckPointer<T> &, const size_t n); 

template <typename Type> 
class T_CheckPointer { 

    // Specific Template Friendship 
    friend T_CheckPointer<Type> 
    operator+ <Type> (const T_CheckPointer<Type> &, const size_t n); 

// other code... 

} 

テンプレート関数のインスタンス化中にエラーがあります。

そして、私はタイプ関数名の後に単語を削除することによって

// Specific Template Friendship 
friend T_CheckPointer<Type> 
    operator+ <> (const T_CheckPointer<Type> &, const size_t n); 

// Specific Template Friendship 
friend T_CheckPointer<Type> 
    operator+ <Type> (const T_CheckPointer<Type> &, const size_t n); 

を変更した場合、その後、すべてが大丈夫になります。

誰でも私に理由を教えていただけますか?詳細について


私は、エラーメッセージ

int iarr[] = {1, 2, 3, 4}; 
T_CheckPointer<int> itcp(iarr, iarr+4); 

呼び出すときに、エラーメッセージがあります:

/usr/include/c++/4.4/bits/stl_iterator_base_types.h: In instantiation of ‘std::iterator_traits<int>’: 
/usr/include/c++/4.4/bits/stl_iterator.h:96: instantiated from ‘std::reverse_iterator<int>’ 
../Classes/T_CheckPointer.hpp:31: instantiated from ‘T_CheckPointer<int>’ 
../PE16.cpp:520: instantiated from here 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:127: error: ‘int’ is not a class, struct, or union type 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:128: error: ‘int’ is not a class, struct, or union type 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:129: error: ‘int’ is not a class, struct, or union type 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:130: error: ‘int’ is not a class, struct, or union type 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:131: error: ‘int’ is not a class, struct, or union type 
+0

エラーメッセージは何ですか? – enobayram

+0

@enobayram、あなたの注意のおかげで、私は記事に入れました。 – Tianyi

+0

** minimal **の例を提供してください。イデーン)問題を表示しますか?あなたはgcc 4.7にアップグレードしようとしましたか? – TemplateRex

答えて

4

はここで、最小限の例です:

template<typename T> struct U { typedef typename T::X X; }; 
template<typename T> void foo(typename U<T>::X); 

template<typename T> struct S; 
template<typename T> void foo(S<T>); 
template<typename T> struct S { friend void foo<T>(S<T>); }; 

template struct S<int>; 

friend宣言が失敗する理由は、コンパイラに要求しているテンプレート引数の完全なリストを提供することにより、使用可能なすべての関数テンプレートを特化し、その署名に最もよく合致するものを選ぶからです。 fooの最初の定義を特殊化すると、不正な形式のプログラムになるという議論を特化した結果がUになります。

テンプレート引数を省略すると、引数から推論されます。そのようなテンプレート引数の控除は、Uの置換失敗がエラー(SFINAE)ではないことを意味する14.8.2 [temp.deduct]、特に14.8.2p8に従って適用されるため。

これは、テンプレート引数をコンテキスト(たとえば、ここでは関数または演算子のパラメータ型)から導き出すことができる場所を省略するのに適しています。 operator +テンプレートID:14.5.4 [temp.friend])であることを確認するには、<>の角かっこを指定する必要があります。

+0

+1これは本当に素晴らしい答えです!また、 '<>'の括弧は、テンプレート関数の代わりに非テンプレート関数が選択されないようにするためのものです。 Herb Sutterの古い列を参照してください。http://www.drdobbs.com/befriending-templates/184403853 – TemplateRex

+0

+1お返事ありがとうございます!あなたの答えは非常に明確です。 @ecatmur – Tianyi

関連する問題