Search code examples
c#c++memory-managementarduino-c++equivalent

Is there a C++ equivalent of the variable discard '_' in C#?


In C#, there's a convenient feature using the underscore _ as a discard variable when one wants to explicitly ignore the result of an operation.

I'm currently looking for an equivalent feature or workaround in C++ that would allow me to discard specific values or save memory allocation when retrieving multiple values from a function.

Example:

Let's say I have a function like this:

void readValues(float& temperature, float& humidity, float& dewpoint, float& tempTrend, float& humTrend) {
    // Some operation to retrieve values
}

If I only need to know the temperature, and I do not have a temperature-specific function, how can I discard the other values in the most memory-efficient way?

Or any other approach that could help in conserving memory space when ignoring certain return values from functions in an Arduino/ESP32 environment?

What I'm doing now:

float temperature;
float discard;

readValues(temperature, discard, discard, discard, discard);

What I tried:

float temperature;
readValeus(temperature, null_ptr, null_ptr, null_ptr, null_ptr);
float temperature;
readValues(temperature, 0, 0, 0, 0);

Thank you for any insights or suggestions!


Solution

  • There are a few ways to do what you want. There is no direct equivalent to the discard keyword though.

    Firstly, I wouldn't worry about being memory-efficient in this case. Even if you always returned all values, unused values and their creation may be optimized away.

    Also, output parameters are typically frowned upon in C++. (see F.20: For “out” output values, prefer return values to output parameters) You can pack things into a struct and then simply use the parts of it that you're interested in. Anyhow, here are some possible solutions:

    (1) Function overloading

    void readValues(float& temperature, float& humidity, float& dewpoint);
    void readValues(float& temperature, float& humidity);
    

    The second overload makes dewpoint effectively an optional parameter.

    (2) Pointers and default parameters

    void readValues(float& temperature, float& humidity, float* dewpoint = nullptr);
    // ...
    readValues(t, h);     // don't provide dewpoint
    readValues(t, h, &d); // provide dewpoint
    

    (3) Avoid output parameters

    This is my personal favorite.

    struct Weather {
        float temperature;
        float humidity;
        float dewpoint;
    };
    
    Weather readValues();
    
    // ...
    Weather w = readValues();
    auto [t, h, d] = readValues();
    auto [t, h, _] = readValues();
    

    (4) [[maybe_unused]]

    void readValues(float& temperature, float& humidity, float& dewpoint);
    // ...
    
    float t, h;
    [[maybe_unused]] float _;
    readValues(t, h, _);
    

    You still have to provide an extra argument, but [[maybe_unused]] expresses intent clearly and suppresses warnings about unused variables, if any.