nathanesau
nathanesau

Reputation: 1721

How to derive from vector class

Please help me understand how to create a derived class from vector. I understand deriving from standard containers is discouraged.

Here is my example:

// Example program
#include <vector>

using namespace std;

struct Card
{
    int suit;
    int value;

    Card(int pSuit, int pValue) : suit(pSuit), value(pValue)
    {
    }
};

struct CardVector : public vector<Card>
{
    void removeCards(const CardVector &cardArr)
    {
        // todo
    }
};

int main()
{
    CardVector cardArr1;
    cardArr1.push_back(Card(1,1)); // works

    vector<Card> cardArr2{Card(1,1)}; // works
    CardVector cardArr3{Card(1,1)}; // doesn't compile

    return 0;
}

which gives the compile error

In function 'int main()':
30:32: error: no matching function for call to 'CardVector::CardVector(<brace-enclosed initializer list>)'
30:32: note: candidates are:
16:8: note: CardVector::CardVector()
16:8: note:   candidate expects 0 arguments, 1 provided 
16:8: note: CardVector::CardVector(const CardVector&)
16:8: note:   no known conversion for argument 1 from 'Card' to 'const CardVector&'
16:8: note: CardVector::CardVector(CardVector&&)
16:8: note:   no known conversion for argument 1 from 'Card' to 'CardVector&&'

Upvotes: 1

Views: 331

Answers (1)

Ted Lyngmo
Ted Lyngmo

Reputation: 117298

You can do it by using the base class constructor (and other methods too):

#include <iostream>
#include <vector>
#include <string>

struct Card {
    std::string name;
};

class CardVector : public std::vector<Card> {

    using std::vector<Card>::vector;                    //   <- like so

    void removeCards(const CardVector& cardVector) {}
    void appendCards(const CardVector& cardVector) {}
};

int main() {
    Card a{"A"}, b{"B"};
    CardVector cv = {a, b};
    for(auto& c : cv) {
        std::cout << c.name << "\n";
    }
}

... but since the destructor of std::vector isn't virtual, be sure that you'll never delete objects though a base class pointer.

To avoid future headache, use composition and create proxy functions for those you need to support.

Lightness Races in Orbit shed some light on the compilation errors: The cause was a missing ctor taking a std::initializer_list and to fix that you can either add one constructor (taking a std::initializer_list<Card> as an argument) or re-use the base class ctor as I did above. LRiO also shared VS to this day does an extra copy of ctor args when you inherit ctors like this which is certainly worth taking in consideration if you're using VS.

Upvotes: 4

Related Questions