Почему я получаю ошибку "A <int>" не является доступной базой "S <int>" для базового класса базового класса?

Я пытаюсь вызвать функцию класса A<F>::f() из класса S, но я получаю следующие ошибки, когда я создаю объект S (S<int>s) и вызываю его f member function (s.f()):

source.cpp: при создании 'int S<F>::f() [with F = int]':
source.cpp: 30: 21: требуется отсюда
source.cpp: 22: 25: ошибка: 'A<int>' не является доступной базой 'S<int>'

Обратите внимание, что это работает, когда я заменяю return A<F>::f(); внутри объявления класса S на return C<A, F>::f();. Но мне интересно, почему я не могу сделать это по-другому...

#include <iostream>

template <typename T> class A {
   public:
      int f();
};

template <typename T> int A<T>::f() {
   return sizeof(T);
}

template <template <typename> class E, typename D> class C : E<D> {
   public:
      int f() {
         return E<D>::f();
      }
};

template <typename F> class S : C<A, F> {
   public:
      int f() {
         return A<F>::f();
      }
};

int main() {

   S<int>s;

   std::cout << s.f();

}

Любая помощь приветствуется, и если вам потребуются дополнительные разъяснения, пожалуйста, не стесняйтесь комментировать.

Обновление

Поскольку эти вопросы решены, я думаю, я должен опубликовать код, который действительно работал:

#include <iostream>

template <typename T> class A {
   public:
      int f();
};

template <typename T> int A<T>::f() {
   return sizeof(T);
}

template <template <typename> class E, typename D> class C : public E<D> {
   public:
      int f() {
         return E<D>::f();
      }
};

class S : public C<A, int> {};

int main() {

   S s;

   std::cout << s.f(); // 4

}

Ответы

Ответ 1

template <typename F> class S : C<A, F> 
                               ^

Вы не указываете наследование public, поэтому по умолчанию оно private, что делает базовые классы недоступными.

Ответ 2

Я думаю, что это просто вопрос использования наследования класса public. Попробуйте:

template <template<class> class E, typename D> class C : public E<D> {
   public:
      int f() {
         return E<D>::f();
      }
};

template <typename F> class S : public C<A, F> {
   public:
      int f() {
         return A<F>::f();
      }
};

Ответ 3

Когда вы пытаетесь вызвать A версию f(), вы используете обозначение A<F>::f(). Если A<F> имеет функцию члена static f(), эту функцию действительно вызывали. Однако A<F> имеет только функцию f() не static, т.е. Вызов неявно переводится на this->A<F>::f(). Однако S<F> не имеет A<F> в качестве доступной базы (это база private C<A, F>). По внешнему виду вы хотите делегировать C<A, F> версию f():

C<A, F>::f();

который должен работать, потому что C<A, F> является доступной базой S<int> или сделать базу E<D> C доступной, сделав ее либо public, либо protected.