Search code examples
c++algorithmnamingidioms

How to handle classes with differently named member functions in algorithms?


I have implemented an algorithm in C++. That algorithm can work on different things (objects) that have some properties in common. The algorithm needs to call some member functions of those objects. So, of course, it needs function names to do so. Now, the problem is, the things the algorithm may work on can be quite different. Consider the following illustrating code snippet for example:

struct Zoo {
   using NumAnimals = unsigned short;

   Animal GetAnimal();
   NumAnimals GetNumAnimals();

};

struct Library {
   using NumBooks = size_t;

   Book GetBook();
   NumBooks GetNumBooks();
};

template<typename T>
void f(T t) {
    do_something(t.Get???(), t.GetNum???()); // Get what?
}

What to put instead of the question marks?

I think it would be very inconvenient to replace GetAnimal() and GetBook() by GetThing(), GetItem(), GetObj() or something similar and then have f call that function. Likewise with GetNumAnimals() and GetNumBooks(). But how can I call algorithm f on instances of both classes? Can we build some kind of "name translation" (aliases) here without cluttering Zoo and Library up?

One potential solution that comes to my mind is to derive a class from Zoo and Library, respectively, that "proxies" the calls in f, e.g., for Zoo:

struct ZooProxy : public Zoo {
    using Item = Animal;
    using NumItems = NumAnimals;

    Item GetItem() { return GetAnimal(); }
    NumItems GetNumItems() { return GetNumAnimals(); }
};

and then replace the ??? in f by Item and Items, respectively.

Are there other (better) options?


Solution

  • It does not make sense to change the classes Zoo and Library just for the sake of f.

    It will be better to create overloaded functions for the purposes of f. You can add f-specific code in those functions without affecting the classes themselves.

    template<typename T>
    void f(T t) {
        do_something(geItemForF(t), getNumForF(t));
    }
    
    Animal const& geItemForF(Zoo const& zoo) { ... }
    int getNumForF(Zoo const& zoo) { ... }
    
    Book const& geItemForF(Libraryconst& library) { ... }
    int getNumForF(Libraryconst& library) { ... }