> I would probably approach the problem by defining some abstraction for a hand
> and use the hand itself to find the lowest-valued card(s) as required.
I typically wouldn't do something like that. I would design a hand class that knows about the cards it holds, but is unaware of the rules of any particular game. The idea is that a hand would be a minimal, but complete, abstraction, reusable in a variety of game scenarios: it has no business knowing whether an ace ranks below a king, or if spades have a higher rank than hearts or whether the two of clubs is a wild card.
To encapsulate the interaction between the hands as per the rules of the game, I would typically use a mediator (which "asks" the hands, and then decides what should be done with them). https://sourcemaking.com/design_patterns/mediator
If the rule involves only one hand (requires no adjudication among several objects), a strategy object that encapsulates the behaviour would probably be a more appropriate option. https://sourcemaking.com/design_patterns/strategy
I'm inclined to avoid creating a new hand class at all: a hand is nothing except a collection of cards, so perhaps a vector is sufficient (or perhaps even a pair of iterators): using Hand = std::vector<Card>;
A hand has no business knowing the ordering of cards
Good point. I tried not to imply that a "get smallest card" function should be a member. Surely, the ordering has to be specified somewhere, i.e., as part of a Mediator object or equivalent, although hopefully in a way that eliminates coupling.
For now, I would like to avoid such a sophisticated solution as overkill and try to get away with something like: