2015-10-07 10 views
5

です。テンプレートから継承し、保護されたメンバーにアクセスできるテンプレートからクラスを派生させようとしています。テンプレートが展開される前に、それはテンプレートパラメータベース部材を使用することはできませんので、しかし、それは、これらの権利を持っていない:テンプレートを展開する前のテンプレートの基本クラスへのアクセスは、

using Fun = void (*)(); 

class Base { 
protected: 
    // friend class Derived; // ...need this to eliminate complaint 
    static void something(); 
}; 

template<Fun F> 
class Variant : public Base {}; 

class Derived : public Variant<&Base::something> { // `something()` is protected 
public: 
    void somethingElse() { 
     something(); // doesn't complain about this `something()` 
    } 
}; 

int main() {} 

このことについて奇妙なビットを私にそれがすべてで働いていたfriendingということでした。助けにはならなかった

class Derived : public virtual Base, public Variant<&Base::something> 

:私はバリアント前に、ベースから公開仮想継承を置くことによって「ドアに派生こっそり」可能性がある場合、私は疑問に思いました。

質問:ベース内のすべての派生クラスの明示的な言及を避けるためのいくつかの他のトリックがあるが、それでもテンプレートパラメータのためにそれから保護されたメンバーを選ぶためのアクセス権を持っていますか?

(注:。。でもfriendingが、その場合には助けにはならないような古いgccの、4.6.3でこれをしようとすると、見えます、そのためのサポートはやや新しいものであると思われるので)

+3

関連:[CWG 372](http://wg21.cmeerw.net/cwg/issue372)および[CWG 580](http://wg21.cmeerw.net/cwg/issue580)。 clang ++とg ++の現在のバージョンでさえ、後者の欠陥に対して提案された解像度を実装していないようです。 – dyp

+0

@dyp私はそれがおそらく "答え"であると思っています。それを1つにしたいですか? – HostileFork

答えて

1

スティックメタ機能への不正なアクセス。ベースからメタ関数クラスを派生させます。 CWG 372に関して

template<typename B> 
struct something_variant : public B { 
    typedef Variant< & B::something > type; 
}; 

class Derived : public something_variant<Base>::type { 
    … 

http://coliru.stacked-crooked.com/a/6bca00455bd3daca

、解像度における重要テキストは、このです:ベース指定子の

[A] CCESS検査全体ベースspecifier-まで延期されなければなりませんリストが見られました。

これは既にC++ 11で受け入れられていますので、あなたの例が拒否されているのは興味深いことです。そして、plugging関連の例コードをC++ 11の標準から最近のClangとGCCに紹介すると、彼らは単純に延期を実装していないことを実証しています。実装は遅延アクセスチェックのセットを表すためにいくつかのデータ構造を必要とするため、ちょっと驚くべきことではありません。

関連する問題