When should I use [[maybe_unused]]?
Asked Answered
M

4

53

What is good about using [[maybe_unused]]? Consider

int winmain(int instance, int /*prevInstance*/, const char */*cmdline*/, int show);

int winmain(int instance, [[maybe_unused]] int prevInstance, [[maybe_unused]] const char *cmdline, int show);

Some might insist that using comments is ugly, because this keyword was made and intended to be used under these circumstances, and I totally agree with it, but the maybe_unused keywords seems a bit too long to me, making the code slightly harder to read.

I would like to follow the standard as "strictly" as I can, but is it worth using?

Martguerita answered 16/3, 2018 at 12:29 Comment(9)
"When should I use [[maybe_unused]]?" - I''d argue "never". Unless you have a crappy compiler.Blinni
@JesperJuhl what about the crappy compiler?Maxim
@JesperJuhl If you conditionally (like macros) exclude code that uses a variable for debugging purposes, then it's useful.Auroraauroral
@JesperJuhl - You can't blame a compiler when it's being sabotaged by macros.Jovian
@JesperJuhl what... does that have to do with anything? The problem with unused parameters/variables is that they generate warnings ...Maxim
Simply turn off this compiler warning via compiler switch or something and you're done. This warning is never useful. Never. (Because: It will never uncover a bug you wrote.)Ynez
@Ynez The warning can uncover a bug when you intended to use a variable but instead used the wrong one.Occult
@JordanMelo - and there happened to be no other reference to this one ... well, I suppose it could happen ... some day, to some one ... in the mean time it's a PITA for everyone else ...Ynez
@Ynez It just caught a bug for me at compile time 5 minutes ago :)Occult
G
109

If the parameter is definitely unused, [[maybe_unused]] is not particularly useful, unnamed parameters and comments work just fine for that.

[[maybe_unused]] is mostly useful for things that are potentially unused, like in

void fun(int i, int j) {
    assert(i < j);
    // j not used here anymore
}

This can't be handled with unnamed parameters, but if NDEBUG is defined, will produce a warning because j is unused.

Similar situations can occur when a parameter is only used for (potentially disabled) logging.

Galvin answered 16/3, 2018 at 12:32 Comment(1)
Who would have thought that the "maybe" in maybe_unused is actually important...Maxim
J
78

Baum mit Augen's answer is the definitive and undisputed explanation. I just want to present another example, which doesn't require macros. Specifically, C++17 introduced the constexpr if construct. So you may see template code like this (bar the stupid functionality):

#include <type_traits>

template<typename T>
auto add_or_double(T t1, T t2) noexcept {
    if constexpr (std::is_same_v<T, int>)
        return t1 + t2;
    else
        return t1 * 2.0;
}

int main(){
    add_or_double(1, 2);
    add_or_double(1.0, 2.0);
}

As of writing this, GCC 8.0.1 warns me about t2 being unused when the else branch is the instantiated one. The attribute is indispensable in a case like this too.

Jovian answered 16/3, 2018 at 13:0 Comment(7)
Nice example, it's good to show that not only "evil" macros can cause this.Galvin
I would argue that this is a QoI issue :)Auroraauroral
@Rakete1111, QoI of the compiler?Uttermost
@Uttermost yes exactlyAuroraauroral
@Uttermost QoI meaning Quality of Implementation ?Doublepark
@GabrielDevillers, it seems so. (please ask Rakete111 to confirm)Uttermost
@Auroraauroral QoI meaning Quality of Implementation ?Doublepark
M
2

I find [[maybe_unused]] is useful when you have a set of constants that define a set configuration constants that may or may not be used depending on the configuration. You are then free to change the configuration without having to define new constants and worrying about unused constants.

I use this mainly in embedded code where you have to set specific values. Otherwise enumerations are generally better.

Melda answered 13/7, 2022 at 15:31 Comment(0)
N
2

Use it to suppress compiler warnings of unused variables. Whether or not you choose to use this approach depends on the coding standards and practices of the team or organization you're working with.

In some workplaces, using the approach of commenting out unused variables like this:

bool f (auto /*unusedVariable*/) {return false;}

is common practice. It effectively communicates the intention to keep the variable, even if it appears unused.

Conversely, in other development environments, using techniques like macros might be preferred to address this issue and keep the codebase clean from such comments.

bool f (auto unusedVariable) 
{
   UNUSED (unusedVariable);
   return false;
}

Ultimately, the choice between these methods or any other approach should be made in line with the coding conventions and requirements of your specific project or team. There's no one-size-fits-all answer, and what's important is to maintain consistency within your codebase.

Here's an example where [[maybe_unused]] is commonly accepted:

#include <algorithm>
#include <iostream>
#include <vector>
 
int main()
{
   std::vector<int> v {0, 1, 2, 3 };
   
   std::cout << std::count_if (v.begin (), v.end (), [] (int i) {return (i & 1);}) << "\n";
   std::cout << std::count_if (v.begin (), v.end (), [] ([[maybe_unused]] int i) {return true;}) << "\n"; // Compiles without a warning
   std::cout << std::count_if (v.begin (), v.end (), [] (int i) {return false;}) << "\n"; // Produces a warning
}
Nuncio answered 10/10, 2023 at 19:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.