0

How can I pass an Object of type Push or Pull into an Object of type Object Pool?

I am simulating an Object Pool in C++. I've made a function called Request() which can receive a Parameter of either Pull or Push.

Is it possible? And if so, how?

Thank you in advance.


Here is the code example:

template <class T>
class ObjectPool {
    public:
        T Request(T* Object) {
            // This is the part that seems unclear to me.
            // Basically, in Pseudocode it looks like:
            // if Object.type == Pull, then do:
            //     Steps to Generate an Object.
            // else if Object.type == Push:
            //     Steps to store an Object.
        }

        ObjectPool() {
        }

        ~ObjectPool() {
        }
}
Ed The ''Pro''
  • 875
  • 10
  • 22
  • 1
    you can overload the request function, but it is hard to be more precise without the real code – Tyker Jun 27 '18 at 08:28
  • 2
    Overloading perhaps? It's kind of unclear exactly what you're doing and what you want to accomplish. Please [read about how to ask good questions](http://stackoverflow.com/help/how-to-ask), and learn how to create a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve). I also recommend you read [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/), and *all* of http://idownvotedbecau.se/ to learn some reasons your question might get voted down. – Some programmer dude Jun 27 '18 at 08:28
  • @acraig5075 I gave this answer below, I also think it's the best idea. einpoklum solution with templates is a bit tricky for neophytes. – user30701 Jun 27 '18 at 08:46
  • I have added a code example. Both of the answers given by @user30701 and einoklum helped me. – Ed The ''Pro'' Jun 27 '18 at 08:51
  • @EdwinPratt: But note that I had to essentially write 2 answers, with only one being properly relevant to your specific case. That's a lesson in why it's important to include example code. – einpoklum Jun 27 '18 at 09:08
  • @einpoklum Thank you. From now on, I will add code examples. – Ed The ''Pro'' Jun 27 '18 at 09:11

2 Answers2

3

You can do it by inheritance, both your Pull and Push object inherit from a parent class.

class Push: public BaseClass { /* ... */ };
class Pull: public BaseClass { /* ... */ };

void Request(BaseClass* action) { /* ... */ }

So you can give ether a Pull or a Push Object to your Request function.

user30701
  • 308
  • 1
  • 6
  • But this would mean that OP must have a Pool of BaseClass, which may contain both Push'es and Pull's. – einpoklum Jun 27 '18 at 09:09
  • Not as I intend it, push and pull are instruction for the pool, those objects may contains information about the instruction (how many object to push/pull, callbacks, etc...). The pool instanciate its own pool objects. – user30701 Jun 27 '18 at 09:36
1

If the Pool class is templated on the request parameter:

You have two options:

  1. Just make your pseudocode into code:

    T Request (T* Object) {
         static_assert(std::is_same_v<T,Push> or std::is_same_v<T,Pull>,
             "Unsupported pool element type");
         if constexpr (std::is_same_v<T,Pull>) {
             /* do stuff for Pulls */
         }
         else { // i.e. std::is_same_v<T,Push> {
             /* do stuff for Pushes */
         }
    };
    
  2. Not provide a general implementation, but rather two specializations, for Pull and for Push respectively.

    template <typename T>
    class Pool{
        /* ... */
        T Request (T* Object);
        /* ... */
    };
    
    template<> Pool<Pull>::Request(Pull* pull) { /* etc. */ }
    template<> Pool<Push>::Request(Push* push) { /* etc. */ }
    

If the Pool class is not templated on the request parameter:

You need to be more specific in your question, but:

  1. (As @Tyker and @SomeProgrammerDude suggest) you can overload the request method:

    class Pool {
        /* ... */
        SomeType request(const Push& p);
        SomeType request(const Pull& p);
    };
    
  2. You can template the request method over the request type:

    class Pool {
        /* ... */
        template <typename T>
        SomeType request(const T& request_param);
    };
    
  3. You could use a variant, where values can have either one type or another type - like a (disjoint) union of the two types:

    class Pool {
        /* ... */
        using request_param_type = std::variant<Push, Pull>;
        template <typename T>
        SomeType request(request_param_type request_param);
    };
    

    and then you can have code which explicitly decides (at run-time) what to do for what class. It will not be templated code, i.e. you can expose the header without the implementation.

    Now the code above is a bit problematic, since the way I've written it, you're making a copy of the Push or Pull object and you might not want to do that. In that case try:

    template<class...Ts>
    using variant_of_const_refs = std::variant<std::reference_wrapper<const Ts>...>;
    
    class Pool {
        /* ... */
        using request_param_type = variant_of_const_refs<Push, Pull>;
        template <typename T>
        SomeType request(request_param_type request_param);
    }
    
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • I'd like to learn more about Generics. If you can, may you please comment a link for Generics? – Ed The ''Pro'' Jun 27 '18 at 09:01
  • 1
    @EdwinPratt: Well, there's a series of 4 videos on YouTube you could take a look at, starting with [this one](https://www.youtube.com/watch?v=AvUMMljFzfI), but you should really take one of the [textbooks](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282). If you want to go in deep, there's a specific textbook on the subject: [C++ Generics: The Complete Guide](http://tmplbook.com/) (make sure you read the second, not the first, edition.) – einpoklum Jun 27 '18 at 09:06