Home > front end >  DElem<T,N> derives from BElem<T> and DContainer<DElem<T,N>> derives from BCo
DElem<T,N> derives from BElem<T> and DContainer<DElem<T,N>> derives from BCo

Time:04-23

The question is easy to explain in code.

I have coded several template classes that they derive from a unique template class:

template<typename T,unsigned N> 
struct DElem : 
    public BElem<T> 
{};

My problem arises when I have to code a container of these anterior derived types from a container of the base class:

template<typename T, unsigned N>
struct DContainer<DElem<T,N>> : 
    public BContainer<BElem<T>>
{};

In my concrete case, Container could be std::tuple or std::array.

My first approximation is:

template<typename T, T B, std::size_t N>
struct DContainer : 
    public std::array<BElem<T>,N> 
{

   // This container is to hold **DElem<T,B>**
   // 
   // This class has to do a cast for every
   // 
   // **DElem<T,B>** (that is what the DContainer holds) 
   //
   // to **BElem\<T\>**
   // 
   // *If this task is easy I don't found the way*

};

Someone has an idea to do these tasks more easy or some other design more appropiate?

CodePudding user response:

You are out of luck. A container of DElem<T, N> is not substitutable for a container of BElem<T>. If it could, the following nonsense would be allowed.

DContainer<T, 10> d10Container;
BContainer<T> & bContainer = d10Container;
DElem<T, 20> d20;
bContainer.push_back(d20); // pushed a d20 into a container of d10

What you can have is a view of BElem<T>

template<typename T>
class BView {
    class iterator {
        using value_type = BElem<T>;
        using reference = BElem<T> &;
        using pointer = BElem<T> *;
        using difference_type = std::ptrdiff_t;
        using iterator_category = std::forward_iterator_tag; // or whatever
        reference operator*();
        pointer operator->();
        // etc...
    };

    virtual iterator begin() = 0;
    virtual iterator end() = 0;

    // no insert / push_back / whatever
};

You probably want to hide (or delete) the assignment operator of BElem<T>, because polymorphic assignment is also fairly nonsensical.

Now you have a shared base class for all your DContainer<T, N>s which doesn't permit nonsense.

Alternatively, if you don't need runtime polymorphism, you can just define a concept for BContainer. Using the pre-concept Container requirements as a base:

template<container C, typename T>
concept BContainer = std::derived_from<typename C::value_type, BElem<T>>;
  • Related