R zu
R zu

Reputation: 2074

Conversions in a chain of classes

I have an object S. S is composed of layers S0, S1, S2 ... just like a stack of stackable drawers.

I want to create a chain of template classes A, B, C such that:

  1. They represents proxies to different layers of the S object.
  2. Even during template instantiation, C can convert to B, which can convert to A.
  3. A, B, and C have different sets of methods.

The problem is that if I use public inheritance, then C will get the methods of A and B.

Test:

#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;
}

Upvotes: 1

Views: 57

Answers (2)

Jaege
Jaege

Reputation: 1863

I'm not sure if I understand what you want. But one way to do it is changing the access level of base class member in derived class. For example:

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
};

Upvotes: 1

R zu
R zu

Reputation: 2074

"Just" need 0 + 1 + 2 + ... + i conversion operators for layer Si

Or one template conversion operator if their attributes are all the same.

But this still need some way to control the conversions.

#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;
}

Upvotes: 0

Related Questions