2015-10-07 81 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() {} 

這個對我有點怪異的是,邀請好友它的工作在所有。我不知道是否會「偷偷在門派生」通過把公共虛擬繼承自基地變前:

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

沒有幫助。

問題:是否還有其他一些技巧可以避免顯式提及Base中的所有派生類,但是仍然可以從中爲模板參數選擇受保護的成員?

(注意:在舊的GCC,4.6.3嘗試這個,貌似連邀請好友不在這種情況下幫助如此看來這種支持是有點新)

+3

相關:[CWG 372](http://wg21.cmeerw.net/cwg/issue372)和[580 CWG(http://wg21.cmeerw.net/cwg/issue580)。看來即使當前版本的clang ++和g ++也沒有爲後一個缺陷實現建議的分辨率。 – dyp

+0

@dyp我在想這可能是「答案」,或者離我們很近。想要成爲一個? – HostileFork

回答

1

棒的違反訪問元功能。從基地派生元函數類。

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

關於CWG 372,在分辨率的臨界文本是這樣的:

[A] CCESS基符的檢查必須推遲到整個基specifier-名單已被看到。

這已經被C++ 11接受了,所以有趣的是你的例子被拒絕了。而且,plugging相關的示例代碼從C++ 11標準到最近鏘和GCC表明,他們根本沒有實現的推遲。這至少有點不令人吃驚,因爲實現需要一些數據結構來表示一組延遲訪問檢查......對於一個角落案例來說是相當高的工作量。