【问题标题】:Access on base class of template prior to expansion of the template being derived from在扩展派生的模板之前访问模板的基类
【发布时间】:2016-01-04 03:38:12
【问题描述】:

我正在尝试从模板公开派生一个类,使其继承自基类并获得对受保护成员的访问权限。但是在扩展模板之前它没有这些权限,所以它不能使用 Base 成员作为模板参数:

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() {}

对我来说,这件事的奇怪之处在于交友它完全有效。我想知道我是否可以通过将来自 Base 的公共虚拟继承放在 Variant 之前“偷偷摸摸”:

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

这没有帮助。

问题:是否有其他技巧可以避免显式提及 Base 中的所有派生类,但仍然可以从中挑选受保护的成员作为模板参数?

(注意:在较旧的 gcc 4.6.3 上尝试此操作,在这种情况下看起来即使是加好友也无济于事。所以似乎对此的支持有点新。) p>

【问题讨论】:

  • 相关:CWG 372CWG 580。似乎即使是当前版本的 clang++ 和 g++ 也没有实现针对后者缺陷的建议解决方案。
  • @dyp 我想这可能是“答案”或者我们将得到的最接近的答案。想做一个吗?

标签: c++ templates inheritance protected


【解决方案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]必须推迟对基本说明符的访问检查,直到看到整个基本说明符列表。

这已经在 C++11 中被接受,所以有趣的是你的例子被拒绝了。并且,plugging 相关示例代码来自 C++11 标准 到最近的 Clang 和 GCC 中表明他们根本没有实现延迟。这至少有点不足为奇,因为实现需要一些数据结构来表示一组延迟访问检查……对于极端情况来说相当大的努力。

【讨论】:

    猜你喜欢
    • 2012-09-12
    • 2016-02-02
    • 2014-03-13
    • 2019-11-09
    • 2018-09-18
    相关资源
    最近更新 更多