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