2015-10-07 80 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表明,他们根本没有实现的推迟。这至少有点不令人吃惊,因为实现需要一些数据结构来表示一组延迟访问检查......对于一个角落案例来说是相当高的工作量。