HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Seeking proper system for pairing types

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
pairingsystemfortypesproperseeking

Problem

My code below ensures that only land animals can be a "representatives" for Land while only ocean animals can be representatives for Ocean, and so forth for Air, Underground, etc... Just want some feedback about whether this system I've come up with is any good or if there is a better one. Note: I'm using structs instead of classes to keep it simple.

#include 
#include 

struct IAnimal { virtual ~IAnimal() = default; };

template 
struct Animal : virtual IAnimal {};  // Animal can only be pair with T, where T is derived from Place.

struct Place {
    IAnimal* representative;
    virtual bool setRepresentative (IAnimal* a) {
        representative = a;  std::cout 
struct PlaceCRTP : Place {
    virtual bool setRepresentative (IAnimal* a) override {
        if (canUse(a))
            return Place::setRepresentative(a);
        std::cout *>(a) != nullptr;
    }
};

struct Land : PlaceCRTP {};
struct Ocean : PlaceCRTP {};

struct Elephant : Animal {};
struct Moose : Animal {};
struct Deer : Animal {};
struct Whale : Animal {};
struct Shark : Animal {};
struct Crab : Animal, Animal {};  // Note: Crab can represent Ocean or Land!

int main() {
    Land land;
    Elephant elephant;
    Whale whale;
    land.setRepresentative(&elephant);  // Done.
    land.setRepresentative(&whale);  // Cannot be done.

    std::list allAnimals, landCandidates;
    for (int i = 0; i < 10; i++) {
        allAnimals.push_back (new Elephant);
        allAnimals.push_back (new Whale);
        allAnimals.push_back (new Moose);
        allAnimals.push_back (new Shark);
        allAnimals.push_back (new Crab);
    }
    for (IAnimal* a : allAnimals)
        if (land.canUse(a))
            landCandidates.push_back(a);
    std::cout << allAnimals.size() << std::endl;  // 50
    std::cout << landCandidates.size() << std::endl;  // 30 (10 Elephants, 10 Moose, 10 Crabs)
}


One drawback I can think of right away, is that the repeated dynamic casts cost performance, but looking up a

Solution

The design of Place.canUse(Animal) suggests that places use animals.
But in reality it's the other way around.
The question is not if land can use a whale,
but if a whale can "use" land.
I suggest to invert the design to Animal.canUse(Place) (or possibly even canInhabit).

If performance is important,
then you can add in Animal one method for each Place type,
for example canUseLand, canUseOcean.
After all, do you seriously need to consider future expansion of place types?
It's the animal kingdom that's likely to grow.
And the canUseX methods only need to be implemented in higher level classes,
the vast majority will be happy to inherit.

Context

StackExchange Code Review Q#78467, answer score: 2

Revisions (0)

No revisions yet.