#how to make a free function generic over two structs

26 messages · Page 1 of 1 (latest)

sterile jay
#

so i have this function```cpp
std::ostream &operator<<(std::ostream &os, const Deck &deck) {
std::ostringstream repr;

for (size_t i = 0; i < deck.cards.size(); ++i) {
    repr << to_string(deck.cards[i]);
    
    if (i != deck.cards.size() - 1) {
        repr << " ";
    }
}

return os << repr.str();

}

and these two structs```cpp
struct Deck {
    std::vector<Card> cards;

    Deck();
    Card draw();

private:
    void shuffle();
};

struct Hand {
    std::vector<Card> cards;

    void put(const Card &card);
};

both of these contains std::vector<Card> cards; and i would like the overload function above to work on instances of both Deck and Hand type, how would i do that? i know how to solve this with interfaces/protocols but cpp doesnt seem to have them

bright valveBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

wide spruce
#

Without using a common base which contains the actual vector, youll have to involve templates and concept to achieve this.

sterile jay
#

i.e protocol/interface in swift and go is vastly different from abstract classes in python, im not sure how it is in cpp though

wide spruce
#

I'd prefer interface, because that way if in future you have another type with the same pattern, you wont have to change code for the operator overload

#

As an example

#

;compile

#include <iostream>
#include <sstream>
#include <vector>

enum Card {};
std::string to_string(Card card) { return "card"; }

struct Cardable {
  const std::vector<Card>& get_cards() const { return cards; }
  protected:
    std::vector<Card> cards;
};
struct Deck : public Cardable {
    // std::vector<Card> cards;

    Deck() { cards.push_back(Card{}); }
    Card draw();

private:
    void shuffle();
};

struct Hand : public Cardable{
    // std::vector<Card> cards;

    void put(const Card &card);
};

std::ostream &operator<<(std::ostream &os, const Cardable &c) {
    std::ostringstream repr;

    for (size_t i = 0; i < c.get_cards().size(); ++i) {
        repr << to_string(c.get_cards()[i]);
        
        if (i != c.get_cards().size() - 1){
            repr << " ";
        }
    }

    return os << repr.str();
}

int main()
{
  Deck deck;
  std::cout << deck;
}
sage condorBOT
#
Program Output
card
sterile jay
wide spruce
sterile jay
#

is this inheritance or does it conform to cardable?

wide spruce
#

The reason it returned the const reference to vector is that it was just for an example, in the operator it takes const reference to the Base class so the getter must be a const member too, you can change that to your likeness

wide spruce
sterile jay
#
struct Hand : public Cardable

does this inherit from Cardable or does it put a constraint on Hand to conform to the interface of Cardable?

wide spruce
#

So since the vector was common here I seperated it out into its own class, and now the Hand and Deck inherit from it which makes them both have that vector in them, and in the overload i can just refer to this Base class Cardable and access whats common to both of them.

#

Sorry my english sucks today

#

I dont know how to explain that

#

Guess you can call it an interface for now

#

Theres no special conformance but that the derived classes will have a vector

sterile jay
#

you explained great @wide spruce thank you!

bright valveBOT
#

@sterile jay Has your question been resolved? If so, type !solved :)

sterile jay
#

!solved