Преобразования в цепочке классов - PullRequest
0 голосов
/ 10 мая 2018

У меня есть объект S.S состоит из слоев S0, S1, S2 ... точно так же, как стек стековых ящиков.

Я хочу создать цепочку шаблонных классов A, B, C такой, что:

  1. Они представляют прокси для различных слоев объекта S.
  2. Даже во время создания шаблона C может преобразовывать в B, что может преобразовывать в A.
  3. A, B и C имеют разные наборыметодов.

Проблема в том, что если я использую публичное наследование, то C получит методы A и B.

Тест:

#include <iostream>
// Library
template <typename T>
class A {
public:
    void a() {std::cout << "a\n"; }
    int s_{0};
};

template <typename T>
class B : public A<T> {
public:
    void b() {std::cout << "b\n"; }
};

template <typename T>
class C : public B<T> {
public:
    void c() {std::cout << "c\n"; }
};

// User of library write a function like this
template <typename T>
void foo(A<T>& a) { a.a(); }

// The problem:
int main() {
    C<int> c;
    foo(c);
    c.a();  // <--- how to hide this?
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

Я не уверен, понимаю ли я, что вы хотите. Но один из способов сделать это - изменить уровень доступа члена базового класса в производном классе. Например:

template <typename T>
class C : public B<T> {
public:
    void c() { std::cout << "c\n"; }
private:
    using A::a;  // <-- reduce access level of base class member
};
0 голосов
/ 11 мая 2018

"Просто" нужно 0 + 1 + 2 + ... + i операторов преобразования для слоя S i

Или один оператор преобразования шаблона, если их атрибуты одинаковы.

Но для этого все же нужен какой-то способ управления преобразованиями.

#include <iostream>

template <typename T>
class A {
public:
    A(int& layer) : layer_(layer) {}
    void a() {std::cout << "a\n"; }

    int s_{0};
private:
    int& layer_;
};

template <typename T>
class B {
public:
    B(int& layer) : a_(layer) { }
    template <template<typename> class X, typename T2>
    operator X<T2>() { return a_; }
    void b() {std::cout << "b\n"; }

private:
    A<T> a_;
};

template <typename T>
class C {
public:
    C(int& layer) : b_(layer) {}
    template <template<typename> class X, typename T2>
    operator X<T2>() { return b_; }
    void c() {std::cout << "c\n"; }

private:
    B<T> b_;
};

template <typename T>
class D {
public:
    D(int& layer) : c_(layer) {}
    template <template<typename> class X, typename T2>
    operator X<T2>() { return c_; }
    void c() {std::cout << "c\n"; }

private:
    C<T> c_;
};

template <template<typename> class X, typename T>
void foo(X<T>& a) {
    A<T>(a).a();
}

int main() {
    int v = 1;
    D<int> d(v);
    foo(d);
    return 0;
}
...