c++design-patternsnamespaces

Accessing namespaces via iterators/pointers?


I am currently facing a design/language problem of sorts. I have 3 files, A,B,and C which have their own namespaces defined as A,B,and C respectively. Each namespace has exactly the same function signatures, only implemented differently (think a REST API call with different but similar APIs).
Now my aim is to be able to call these functions from the correct namespace without repeating the function name.

Ideally I'd like to do something like this:

#include <iostream>

#include "A.h"
#include "B.h"
#include "C.h"

enum ns {
    A = 0,
    B = 1,
    C = 2
};
int main() {

    auto NS = {A, B, C}; //these are the namespaces

    if (condition){
        int n = get_index();
        NS[n]::myfunc();
    }
}

where myfunc() is defined, albeit differently, in each source file corresponding to A.h, B.h, and C.h.

Can someone tell me whether there is a way to do this, or suggest an alternate design pattern I should adopt? Thanks

To explain my problem more concretely, I have a DataReader class which fetches data about say cars, from REST endpoints by vendors A, B, C and preprocesses them. I did think of making a class and subclassing them for different vendors, but then won't it be too complicated, having a vendor-specific class inside my DataReader class?


Solution

  • You can create a base class/struct with a pure-virtual method myfunc(),
    and then make A,B and C (each can reside in its namespace if you want them to, but it's not a must) derive from it and implement myfunc.

    You can then store them all in an array, and use a polymorphic call the invoke the proper method based on an index:

    #include <array>
    #include <iostream>
    #include <memory>
    
    struct Base {
        virtual ~Base() = default;
        virtual void myfunc() = 0;
    };
    
    namespace AAA   // using a namespace is optional
    {
        struct A : public Base {
            void myfunc() override { std::cout << "A::myfunc()\n"; }
        };
    }
    
    namespace BBB   // using a namespace is optional
    {
        struct B : public Base {
            void myfunc() override { std::cout << "B::myfunc()\n"; }
        };
    }
    
    namespace CCC   // using a namespace is optional
    {
        struct C : public Base {
            void myfunc() override { std::cout << "C::myfunc()\n"; }
        };
    }
    
    int main() {
        std::array<std::unique_ptr<Base>, 3> objs = {
            std::make_unique<AAA::A>(),
            std::make_unique<BBB::B>(),
            std::make_unique<CCC::C>()
        };
    
        objs[0]->myfunc();
        objs[1]->myfunc();
        objs[2]->myfunc();
    }
    

    Output:

    A::myfunc()
    B::myfunc()
    C::myfunc()
    

    Live demo.

    Notes:

    1. The only reason I used structs instead of classes is to make the demo a few lines shorter (save the public: lines). You can use classes of course instead of them.
    2. I added the namespaces just in case you would like to put your classes in ones (since you mentioned them in the question), although they are not really needed for the solution above.