2011-02-03 16 views
7

テンプレートパラメータが許可されていないため、テンプレートパラメータを友人にすることはできません。どのように私は効果的に同じ事を得ることができますか?私が欲しいものテンプレートパラメータの追加

は、基本的には、それを所有するオブジェクト外使用できないタイプです。どうしてそもそもポイントの横にあるのですが、本当に知っていなければならない場合は、所有リソースの共有の問題に答えるスマートポインタのセットを策定しようとしています。それは自身の所有者宣言しない限り

template < typename T, typename Owner > 
struct accessible_member 
{ 
private: 
    accessible_member() : val(T()) {} 
    accessible_member(T const& t) : val(t) {} 

    operator T&() { return val; } 
    operator T const&() const { return val; } 

    member_ptr<T> operator &() { return member_ptr<T>(val); } 

    friend class Owner; 
}; 

は、このようにクラスがメンバーとしてこのオブジェクトを保持することはできません、それは十分に愚かだ場合は公開する。このように私は何を探していることは、それが働いていた場合、そのようなものですそれはそうであるように、クラスの外で愚かであることは不可能になります。

+2

最後の段落のように、私はbraindeadのコードを防止しようとしていません。 C++では、十分な努力をすれば、誰かがあなたのコードを壊す可能性があるということだけを受け入れる必要があります。 –

+1

@Fred - 'const'とRAIIを含むコード安全対策を導入しようとする試みに対して、同じような愚かな議論を使うことができます。異なる哲学のもとで作業するかもしれませんが、私は、あなたの構文が正しく使いやすく、間違って使いにくいというガイドラインの下でコーディングします。コンストラクト自体の全体的なポイントは、他のものによって提供されていない安全対策を導入することです。私はあなたの疑問に対するあなたの反対を、冗長で、外れていて、かなり率直に攻撃しています。 –

+2

@ NoahRoberts:1)これは正しく使用するのが簡単ではないようです。 2)ConstとRAIIは間違って使いやすい。 3)私の理解の欠如( "私の意見は分かりません")がどのようにして不快に感じるのですか?私を守るために私のために怒っていますか? –

答えて

3

あなたがこれを使用することができ、かつすべての所有者にオーナーを継承させます。

その後、個人 accessible_member で使用されるメソッドをラップする所有者クラスを使用することができます。
accessible_memberは今所有者にアクセス可能です。 Friendは継承されないため、所有者を継承するすべてのクラスで使用できるように必要なメソッドを提供(ラップ)できますaccessible_member

これは、2レベルのソリューションですが、それはカプセル化のレベルを保持します。

template < typename U > 
struct Owner 
{ 
    protected: 
    accessible_member<U> newAccessible_member() { return accessible_member<U>(); } 
    accessible_member<U> newAccessible_member(U const& u) { return accessible_member<U>(u); } 
    ..... 

}; 

template < typename T > 
struct accessible_member 
{ 
private: 
    accessible_member() : val(T()) {} 
    accessible_member(T const& t) : val(t) {} 

    operator T&() { return val; } 
    operator T const&() const { return val; } 

    member_ptr<T> operator &() { return member_ptr<T>(val); } 


    template < typename U> friend class Owner; 
}; 

次に、あなたが保護されたメソッドを使用して所有者を継承構造体に間接的にaccessible_memberを使用することができます。Template Friendsで最後の例で

struct Blah: Owner<int> 
{ 
    void Dosomething() { 
     accessible_member<int> blah= newAccessible_member(); 
    } 
}; 

ルック。

+1

友情は継承されていないので、私はこれがどのように機能するかわかりません。 –

+0

Ownerは、Ownerをラッパーとして使用し、所有者のメソッドを個人的にラップすることができます。 –

+0

私はこの回答の目的もコメントも理解していません。 –

0

何単に自明accessible_memberから継承プライベートネストされたタイプの定義について?それは考えてみると多くの使用のかもしれませんので、まだ元のaccessible_memberタイプは誰にでも利用可能であることを意味する。もちろん、

class Owner 
{ 
    template < typename T > 
    class accessible_member : public ::accessible_member<T> {}; 
}; 

ような何か。

+0

OwnerをOwner :: accessible_memberの友人にし、privateに継承した:: accessible_memberを作成した場合、これはうまくいく可能性があります。しかし、Owner :: accessible_memberには多くのフォワード宣言が必要です。 –

5

あなたはC++ 98/03については正しいです。しかし、C++ 0xの(n3225 11.4/3)は、この構文でこれを行うことができます:あなたのコンパイラは、あなたがそれを行うようになる場合

friend Owner; 

を参照してください。 C++ 0xサポートを有効にしてみてください。そうでない場合の回避策は醜いです:

struct Owner 
{ 
    typedef Owner self; 
}; 

...

その後、あなたのコンパイラに依存するの1:

friend typename Owner::self; 

か:

friend class Owner::self; 
+1

'typedef Owner Owner_typedef;の何が問題なのですか?友人クラスOwner_typedef; '?いずれにしても、構造体パラメータと同じ名前をテンプレートパラメータとして選択することは、本当に悪い考えです。 –

+0

テンプレートのパラメータに 'self'ネストされた型の要件をドロップすることはできますか?テンプレート struct identity {typedef T type; }; 'Owner :: selfをid3: :: typeに変更し、同じコンパイラで動作させますか? –

+0

@BenVoigt:なぜそれは本当に悪い考えですか?いずれにしても、ここでは例として使用しています。 –

1

7.1.5。3 p2は言う:

[注:これが意味する、そのテンプレート 型パラメータT、宣言 フレンドクラスTと クラステンプレート内。 ]

結果として、あなたがそれを任意の意味で使用できるようにするソリューションは、標準に準拠していません。私が見ることができる

+2

状況に対処する標準的な見積もりは、正確には答えではありませんが、確かにそれを下落させることはできません。 –

+2

質問には言及していませんが、実際には、質問自体に言われていないことを言っていないとき、特に "答え"を捨象する大きな理由があります: "標準ではテンプレートパラメータを友人にすることは不可能です" –

0

唯一の回避策はかなり醜いですとCRTP使用しています:

template <typename T> 
struct CanUseAccessibleMember 
{ 
    template <typename T> 
    static const T& get(const accessible_member<T>& m) 
    { return static_cast<const T&>(m); } 

    // Etc. You can even specialize this class. 
}; 

struct ExampleOwner 
    : protected CanUseAccessibleMember<ExampleOwner> 
{ 
    // Do whatever you want with accessible members here 
    // but you have to use the get syntax 
}; 

template <typename T, typename Owner> 
class accessible_member 
{ 
    // Implement members as you did 

    friend struct CanUseAccessibleMember<Owner>; 
}; 
+0

(質問のように)accessible_memberのctors、メソッド、演算子はprivateなので、ExampleOwnerはまだそれらにアクセスできません。 –

+0

@Fred:ベース 'CanUseAccessibleMember'クラスに' get'のようにラッパーを書く必要があります。少数のメンバーしかいないようだから大丈夫です。それが私がそれが醜いと言う理由です。 –

0

限り私が見ることができるように、C++ 98の下で、ほとんど変化して、動作します。

:それはちょうど

struct Wrapper { typedef Owner type; }; 
friend class Wrapper :: type; 

friend Owner; 

を変更g++-4.1 -Wall -Wextra -pedantic -ansi -std=c++98

と私のための任意の警告なしにコンパイル(Template parameter as a friend私はStackOverflowの上でその答えを得た、この質問は何度か来ています)

+0

この一般的な考え方は、ある演算子( '演算子const T&')を 'public'とするときに便利です。これは、何かを「公に読めるが公然と書いてはいけない」とマークする簡単な方法を与える。つまり、そのゲッタとセッターのナンセンスは必要ありません:-) –

関連する問題