为什么不能编译以下 CRTP 层次结构?

Why doesn't the following CRTP hierarchy compile?

我正在尝试实现 class 的 CRTP 层次结构。我对基数 class 感兴趣,可以访问链下派生 class 的数据成员:

#include <iostream>

template <class Derived>
class A {
public:
    void showv() {
        std::cout << static_cast<const Derived*>(this)->v << std::endl;
    }
};

template <class Derived>
class B : public A< Derived > {
    typedef A<Derived> base;
    friend base;
};

class fromA : public A<fromA> {
    typedef A<fromA> base;
    friend base;
protected:
    int v = 1;
};

class fromB : public B<fromB>
{
    typedef B<fromB> base;
    friend base;
protected:
    int v = 2;
};

int main()
{
    // This runs ok
    fromA derived_from_a;
    derived_from_a.showv();

    // Why doesn't the following compile and complains about the protected member?
    fromB derived_from_b;
    derived_from_b.showv();

    return 0;
}

Demo

虽然第一个派生的 class (fromA) 按预期编译和运行,但第二个 (fromB) 派生自 class 派生自 A,没有。

  1. 朋友声明没有通过的原因是什么?
  2. 有任何解决方法的建议吗?

问题是:我朋友的朋友不是我朋友。

fromA你有

typedef A<fromA> base;
friend base;

这使 A<fromA> 成为朋友并且 show 可以访问 fromA 的受保护成员。

fromB你还有

typedef B<fromB> base;
friend base;

但这并不能使 A 成为朋友,而是 B 你的朋友。尽管 A 是 B 的朋友,但这并不意味着它现在也是 fromB 的朋友,这就是为什么您无法在 show.[=28 中访问 v 的原因=]

解决此问题的一种方法是使 typedef A<Derived> base; public 或在 B 中受到保护,然后在 fromB 中添加 friend base::base;授予 A 访问权限。