mercredi 17 mars 2021

C++17 Pass reference to interface of templated class into sibling templated class constructor

Consider the following example:

template <typename Consumer>
class ClassA
{
public:
    template<class... Args>
    explicit ClassA(Args &&... args) :
        consumer_(std::forward<Args>(args)...)
    {

    }

    void consume()
    {
        consumer_.consume();
    }

private:
    Consumer consumer_;
};

template <typename Consumer>
class ClassB
{
public:
    template<class... Args>
    explicit ClassB(Args &&... args) :
        consumer_(std::forward<Args>(args)...)
    {

    }

    void consume()
    {
        consumer_.consume();
    }

private:
    Consumer consumer_;
};

class ClassC
{
public:
    explicit ClassC(int val) :
        val_(val)
    {

    }

    void consume()
    {
        std::cout << "ok " << val_ << std::endl;

    }

private:
    int val_;
};


void usage()
{
    ClassA<ClassB<ClassC>> composed_object(3);
    composed_object.consume();
}

It's a kind of templated bridge (or proxy? or strategy?) pattern, that I can easily compose and change implementation in compile time.

I try to avoid using of dynamic polymorphism due to performance reasons.

So, the question: How to allow ClassB to call some of ClassA methods?

The first thing that comes to my mind is to pass a reference of ClassA to ClassB. But there is a templated class chain and I don't want to change class chain usage.

I can rewrite ClassB as follows:

template <typename Interface, typename Consumer>
class ClassB
{
public:
    template<class... Args>
    explicit ClassB(Interface &interface, Args &&... args) :
        consumer_(std::forward<Args>(args)...),
        interface_(interface)
    {

    }

    void consume()
    {
        consumer_.consume();
    }

private:
    Consumer consumer_;
    Interface &interface_;
};

So, it now takes an additional templated param of parent class Interface and a reference to parent in constructor.

But I have no idea how to specify templated param Interface in ClassA without change the chain usage.

To my mind it's a kind of template param infinity loop.

Aucun commentaire:

Enregistrer un commentaire