Search code examples
c++overloading

General approach to overloading several similar functions


I have this pattern in my code:

public:
    int start(const uint32_t channel);
    int stop(const uint32_t channel);
    void set_current_desc(uint32_t channel, uint64_t cdesc);
    // ...
private:
    const uint32_t channel_;

All functions take in the channel argument. I would like to provide this interface:

public:
    int start(const uint32_t channel);
    int start(void) { return start(channel_); } 
    int stop(const uint32_t channel);
    int stop(void) { return stop(channel_); }
    void set_current_desc(uint32_t channel, uint64_t cdesc);
    void set_current_desc(uint64_t cdesc) { set_current_desc(channel_, cdesc); }
    // ...
private:
    const uint32_t channel_;

Is there a general approach to doing this for all functions at once, or will I have to type it all out? I guess there exists some messy macro method but I would prefer a C++ non-macro solution.

Edit: The initial interface must remain due to backwards compatibility.


Solution

  • You can modify the methods to accept a std::optional with a default value of std::nullopt.

    If the caller does not supply a channel (via the new interface) the channel_ member will be used.
    If the caller supplies a channel (as you requested for backwards compatibility), it will be used.

    This is done using the method std::optional::value_or.

    #include <optional>
    #include <iostream>
    #include <cstdint>
    
    class Test {
    public:
        Test(uint32_t channel) : channel_(channel) {}
    
        void start(std::optional<uint32_t> channel = std::nullopt)
        {
            // Determine `cur_channel` to use:
            uint32_t cur_channel = channel.value_or(channel_);
            // Use `cur_channel` ...
            std::cout << "start, using channel: " << cur_channel << "\n";
        }
    private:
        const uint32_t channel_;
    };
    
    int main() {
        Test test{ 333 }; // `channel_` member will be 333
        test.start();     // will use the `channel_` member of `test`
        test.start(5);    // will use 5 for the current channel (backwards compatibility)
    }
    

    Output:

    start, using channel: 333
    start, using channel: 5
    

    Live demo

    A similar approach can be used for the rest of your methods.