91

In c++03 and earlier to disable compiler warning about unused parameter I usually use such code:

#define UNUSED(expr) do { (void)(expr); } while (0)

For example

int main(int argc, char *argv[])
{
    UNUSED(argc);
    UNUSED(argv);

    return 0;
}

But macros are not best practice for c++, so. Does any better solution appear with c++11 standard? I mean can I get rid of macros?

Thanks for all!

Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
inkooboo
  • 2,904
  • 1
  • 19
  • 24
  • 11
    Sure. Turn off the warning. – Pete Becker Apr 02 '13 at 12:20
  • 67
    No! **Do not do that!** – Lightness Races in Orbit Apr 02 '13 at 12:22
  • 10
    How much better is that macro than expanding it inline? `(void)argc;` is shorter and clearer than `UNUSED(argc);` – David Rodríguez - dribeas Apr 02 '13 at 12:45
  • 23
    I like `unused(argc, argv)` with `template void unused(T&&...){}`. Clear, concise, and without macros. – Xeo Apr 02 '13 at 12:56
  • 6
    oh noes macros must not use macros – Lightness Races in Orbit Apr 02 '13 at 13:25
  • 2
    If a parameter is not used, why is it there in the first place? – marco-fiset Apr 02 '13 at 14:33
  • 7
    Sometimes you need to conform to a certain interface (e.g. when overriding a virtual function or in generic programming). – MadScientist Apr 02 '13 at 14:45
  • 3
    `s/sometimes/most of the time/` – Lightness Races in Orbit Apr 02 '13 at 15:00
  • 21
    @MadScientist but you may leave unnamed argument, or even just comment out it's name. `void foo(int /*unused_arg*/, int used_arg)` – kassak Apr 02 '13 at 15:53
  • @kassak That can't be done for "maybe" unused arguments, e.g. with conditional inclusion where one branch need the arguments and another branch does not. To wrap them also in `#ifdef` is too verbose. There would be [`[[maybe_unused]]`](https://isocpp.org/files/papers/P0212R1.pdf) in C++17, but it comes too late. – FrankHB Mar 24 '16 at 14:06
  • @Xeo That also is not quite ideal because "unused" may be indicating working not only on arguments but also expressions. I use [such construct](https://bitbucket.org/FrankHB/yslib/src/0a81c7bc0edd2993a6310e8ec4e471878cf3e2c1/YBase/include/ydef.h?at=master#ydef.h-970) to explicitly express *intended unsequenced evaluation* on non-`void` expressions. OTOH, "unused" is used more generally, [implemented as cast to void](https://bitbucket.org/FrankHB/yslib/src/0a81c7bc0edd2993a6310e8ec4e471878cf3e2c1/YBase/include/ydef.h?at=master&fileviewer=file-view-default#ydef.h-934). – FrankHB Mar 24 '16 at 14:18
  • @DavidRodríguez-dribeas This is quite close to what I am using but I recently find it can't work for parameter packs. That's why I search for the answer and comes here. Sadly I still fail to find an ideal portable solution. – FrankHB Mar 24 '16 at 14:22
  • You should not give answer in you question. It is unfair wrt who answers your question. – Tomilov Anatoliy May 16 '17 at 06:45

12 Answers12

219

You can just omit the parameter names:

int main(int, char *[])
{

    return 0;
}

And in the case of main, you can even omit the parameters altogether:

int main()
{
    // no return implies return 0;
}

See "§ 3.6 Start and Termination" in the C++11 Standard.

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
Henrik
  • 23,186
  • 6
  • 42
  • 92
  • 12
    And in the case of `main`, you can omit the parameters altogether. And the `return` statement, for that matter. – Mike Seymour Apr 02 '13 at 12:20
  • 4
    @MikeSeymour I actually consider it good practice to omit the return statement. – jtepe Apr 02 '13 at 12:23
  • 7
    @jotep Okay, I'll bite. Why do you consider it good practice? – Peter Wood Apr 02 '13 at 12:52
  • @MikeSeymour If it's the default return value that ends main, I omit it, since it's unnecessary boilerplate. – jtepe Apr 02 '13 at 13:09
  • 6
    I almost always omit `main`'s `return 0` in a testcase, but almost always write the self-documenting `return EXIT_SUCCESS` in production code. _That_'s good practice! – Lightness Races in Orbit Apr 02 '13 at 13:10
  • 34
    this seems like the best answer to me - anything that futzes with macros or templates still doesn't ensure that the variable can't be used afterwards. This both silences the warning _and_ ensures that the (unnamed) parameter can't ever be used. – Alnitak Apr 02 '13 at 13:39
  • @Alnitak: Yet at least two other answers _say the same thing_, plus other things, and actually address the question. This one does not. – Lightness Races in Orbit Apr 03 '13 at 20:57
  • 2
    @LightnessRacesinOrbit About "saying the same thing": this is correct and I'm not sure why my answer receives the most upvotes. Maybe because it was the first one. About "actually addressing the problem": yes I could have explicitly stated, "There is no new C++11 feature", but the answer clearly implies there is no need for such a feature (or to use macros) to silence the warning. – Henrik Apr 04 '13 at 07:33
  • 1
    This works in cases where you never refer to the argument but are forced to receive it (e.g. in main, or a virtual function you are overriding). However, it's less useful if you only refer to the argument in a debug configuration for example. Conditionally omitting the parameter name is going to end up being pretty ugly! :) –  Apr 16 '13 at 08:13
  • 1
    This makes it much harder to read the code - you have to refer to the header where *hopefully* the parameter names have been left in order to understand which variables have been ignored. Better to comment them out. – Timmmm Sep 14 '15 at 08:39
  • 2
    Necro comment, but instead of ommiting them you can always comment them out. It takes four more characters and all the information you will ever need is still on the source, without pesky warnings. – The Marlboro Man Aug 17 '16 at 18:48
  • this is great. and if you have to provide a default value, omit the name but you need to keep the value. eg, `void foo(int a = 0, int unused = 0)` -> `void foo(int a = 0, int /* unused */ = 0)` – orion elenzil Sep 24 '21 at 18:39
60

There is the <tuple> in C++11, which includes the ready to use std::ignore object, that's allow us to write (very likely without imposing runtime overheads):

void f(int x)
{
    std::ignore = x;
}
woolstar
  • 5,063
  • 20
  • 31
Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
  • 4
    Considering this is in the standard library and therefore doesn't involve having to write custom functions I'd say this is the best solution! – BrainStone Oct 10 '16 at 01:30
  • 4
    This class is "Intended for use with std::tie when unpacking a std::tuple", not for this use case. I would say it's a solution, but probably not the best. – Maestro Sep 07 '18 at 13:37
  • 1
    I like this ignore actually.. Ofc, if you can remove the parameter, remove this instead (that would be the best solution in all cases). – Melroy van den Berg Jun 15 '19 at 00:40
47

I have used a function with an empty body for that purpose:

template <typename T>
void ignore(T &&)
{ }

void f(int a, int b)
{
  ignore(a);
  ignore(b);
  return;
}

I expect any serious compiler to optimize the function call away and it silences warnings for me.

MadScientist
  • 3,390
  • 15
  • 19
  • T && will not accept parameter (parameter is l-value), will it? Would ignore(T const &) be more suitable? – Suma Apr 02 '13 at 12:58
  • 22
    When `T` is a template parameter, `T&&` is a *universal reference* which binds to anything. – Angew is no longer proud of SO Apr 02 '13 at 13:02
  • @MadScientist: Hmm, interesting...! – Lightness Races in Orbit Apr 02 '13 at 13:19
  • 4
    +1 Even though *Xeo*'s advanced version from his comment isn't even mentioned. – Christian Rau Apr 02 '13 at 14:33
  • 13
    Why ignore the built-in method? Simply omit the parameter name. – Jack Aidley Apr 02 '13 at 17:21
  • You could use variadic template to write something like `ignore(a, b, anythingElseThatBothersYou);` – Sam Apr 03 '13 at 07:05
  • 28
    -1, this is ridiculous and an unnecessary contraption, especially when you can just omit the param name. Frankly, it bothers me that this has 25 upvotes somehow. – TC1 Apr 03 '13 at 21:19
  • 6
    @TC1 This is making your code explicit about what it does and why. Having unused parameters or variables is a smell in your code and this makes it explicit. Turning off the warning makes your code smell more. – dascandy Apr 16 '13 at 08:35
  • 1
    @dascandy there is no warning if you simply omit the name and having no name to reference the variable makes it explicit that you do not use it without having to add bloat. – josefx Apr 20 '13 at 11:21
  • Try to use it in a `constexpr` function. – jweyrich Jun 19 '13 at 05:23
  • 4
    unname them, so the function accepts the parameter, but does not assign it to any variable: `int main( int /* argc */, char ** /* argv */ )` – Xavi Montero Aug 24 '14 at 16:46
  • 2
    Don't reinvent the wheel ! Use boost, see [that answer below](http://stackoverflow.com/a/24310846/888576) – Jean Davy Aug 07 '15 at 06:36
  • I understand the question was for parameters but his answer can be used for RAII-style class like std::lock_guard. You don't "use" this kind of class and don't want a warning... – Janosimas Sep 11 '15 at 13:09
  • The name is not good enough and might conflict to [`std::ignore`](http://www.eel.is/c++draft/tuple.creation#7) if one has used `using namespace std;` naively. – FrankHB Mar 24 '16 at 14:10
  • Maybe one should declare the ```ignore``` function ```inline```. (If the function is put into a header file and the compiler does **not** optimize, then there might be multiple instances of the same specialization in the object files.) – ManuelAtWork Jul 25 '17 at 11:26
  • boost/core/ignore_unused implements it the same way, so I think it's a good solution. If boost found that this method was useful enoug to include it in its library, I would say there must be good reason not to just comment out the parameter names... – Maestro Sep 07 '18 at 13:42
44

To "disable" this warning, the best is to avoid writing the argument, just write the type.

void function( int, int )
{
}

or if you prefer, comment it out:

void function( int /*a*/, int /*b*/ )
{
}

You can mix named and unnamed arguments:

void function( int a, int /*b*/ )
{
}

With C++17 you have [[maybe_unused]] attribute specifier, like:

void function( [[maybe_unused]] int a, [[maybe_unused]] int b )
{
}
Nikko
  • 4,182
  • 1
  • 26
  • 44
  • 3
    I used to do this, but it quickly becomes a pain since you can no longer comment out large chunks of code with `/* ... */` – Ponkadoodle Dec 14 '14 at 07:07
  • 2
    It's true but with modern IDEs I guess if you select a block to comment automatically, it will add a bunch of "//" at the beginning of each line. That's what Eclipse CDT does. Personally, I only use the first example with no name. (you can put names in the declarations in a .h file for instance). – Nikko Dec 15 '14 at 08:30
  • 5
    @Wallacoloo When I want to comment out large chunk of code, I use #if 0 ... #endif, which are allowed to be nested and never conflict with existing /* ... */ comments. – Dmitry Frank Jun 24 '15 at 15:37
  • 1
    @DmitryFrank And most editors and IDEs support graying out `#if 0` blocks as a special case even if they don't support full preprocessor intellisense. – Thomas Jan 17 '18 at 11:17
29

Nothing equivalent, no.

So you're stuck with the same old options. Are you happy to omit the names in the parameter list entirely?

int main(int, char**)

In the specific case of main, of course, you could simply omit the parameters themselves:

int main()

There are also the typical implementation-specific tricks, such as GCC's __attribute__((unused)).

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
15

What do you have against the old and standard way?

void f(int a, int b)
{
  (void)a;
  (void)b;
  return;
}
jcayzac
  • 1,441
  • 1
  • 13
  • 26
  • I find that some compilers are happy with this, but _some_ compilers are pickier than others. Cross Platform work needs to be tested in all targeted OS and compilers to be sure they are all happy with the solution. – Jesse Chisholm Mar 31 '17 at 19:32
14

Macros may not be ideal, but they do a good job for this particular purpose. I'd say stick to using the macro.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • 6
    +1: In this instance, they cause zero harm and solve a problem. I don't see any reason (beyond the ridiculous baseless mantra of "never use a macro") not to employ them here. – Lightness Races in Orbit Apr 02 '13 at 12:29
  • 1
    What is the benefit of a macro over omitting the parameter name altogether? – Micha Wiedenmann Apr 02 '13 at 12:36
  • @LightnessRacesinOrbit: As highlighted by Angew, one issue is that you can actually use the parameter before/after using the macros; silly right ? Well, in code that is heavy with preprocessing directives it's not immediate that you are currently in a branch that is using the parameter or not :( – Matthieu M. Apr 02 '13 at 12:39
  • 1
    @MichaWiedenmann: Some parameters may only be used when some preprocessing constants are set (typically, in Debug). – Matthieu M. Apr 02 '13 at 12:39
  • 2
    @MatthieuM.: I'd call the macro `MAYBE_UNUSED`, for that reason; I typically don't care if I've said "don't worry if I don't use this below" but go on to do so anyway. – Lightness Races in Orbit Apr 02 '13 at 12:43
  • @LightnessRacesinOrbit: fair enough :) – Matthieu M. Apr 02 '13 at 12:50
  • 2
    Ok, so the correct thing is probably to call it "HIDE_UNUSED_WARNING". But I still think that using a macro here is a perfectly valid idea. As long as the macro is named in such a way that it doesn't cause confusion and/or conflicts with other code. – Mats Petersson Apr 02 '13 at 12:53
  • @MatthieuM. if the use of the parameters are only used inside some `#ifdef` blocks, you could put the name of the parameter inside such a conditional block too. – frozenkoi Apr 02 '13 at 23:14
  • @frozenkoi: Yes... but it's quite cumbersome because `#ifdef` and `#endif` directives need be placed on a line of their own, which really screw up the function header... to the point of it being nigh unreadable. – Matthieu M. Apr 03 '13 at 06:53
13

The Boost header <boost/core/ignore_unused.hpp> (Boost >= 1.56) defines, for this purpose, the function template boost::ignore_unused().

int fun(int foo, int bar)
{
  boost::ignore_unused(bar);
#ifdef ENABLE_DEBUG_OUTPUT
  if (foo < bar)
    std::cerr << "warning! foo < bar";
#endif

  return foo + 2;
}

PS C++17 has the [[maybe_unused]] attribute to suppresses warnings on unused entities.

manlio
  • 18,345
  • 14
  • 76
  • 126
11

There's nothing new available.

What works best for me is to comment out the parameter name in the implementation. That way, you get rid of the warning, but still retain some notion of what the parameter is (since the name is available).

Your macro (and every other cast-to-void approach) has the downside that you can actually use the parameter after using the macro. This can make code harder to maintain.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
0

I really like using macros for this, because it allows you better control when you have different debug builds (e.g. if you want to build with asserts enabled):

#if defined(ENABLE_ASSERTS)
  #define MY_ASSERT(x) assert(x)
#else
  #define MY_ASSERT(x)
#end

#define MY_UNUSED(x)

#if defined(ENABLE_ASSERTS)
  #define MY_USED_FOR_ASSERTS(x) x
#else
  #define MY_USED_FOR_ASSERTS(x) MY_UNUSED(x)
#end

and then use it like:

int myFunc(int myInt, float MY_USED_FOR_ASSERTS(myFloat), char MY_UNUSED(myChar))
{
  MY_ASSERT(myChar < 12.0f);
  return myInt;
}
steeveeet
  • 639
  • 6
  • 25
0

I have my own implementation for time critical segments of code. I've been researching a while a time critical code for slow down and have found this implementation consumes about 2% from the time critical code i have being optimized:

#define UTILITY_UNUSED(exp) (void)(exp)
#define UTILITY_UNUSED2(e0, e1) UTILITY_UNUSED(e0); UTILITY_UNUSED(e1)
#define ASSERT_EQ(v1, v2) { UTILITY_UNUSED2(v1, v2); } (void)0

The time critical code has used the ASSERT* definitions for debug purposes, but in release it clearly has cutted out, but... Seems this one produces a bit faster code in Visual Studio 2015 Update 3:

#define UTILITY_UNUSED(exp) (void)(false ? (false ? ((void)(exp)) : (void)0) : (void)0)
#define UTILITY_UNUSED2(e0, e1) (void)(false ? (false ? ((void)(e0), (void)(e1)) : (void)0) : (void)0)

The reason is in double false ? expression. It somehow produces a bit faster code in release with maximal optimization.

I don't know why this is faster (seems a bug in compiler optimization), but it at least a better solution for that case of code.

Note: Most important thing here is that a time critical code slow downs without above assertions or unused macroses in release. In another words the double false ? expression surprisingly helps to optimize a code.

Andry
  • 2,273
  • 29
  • 28
-2

windows.h defines UNREFERENCED_PARAMETER:

#define UNREFERENCED_PARAMETER(P) {(P) = (P);}

So you could do it like this:

#include <windows.h>
#include <stdio.h>
int main(int argc, char **argv) {
  UNREFERENCED_PARAMETER(argc);
  puts(argv[1]);
  return 0;
}

Or outside of Windows:

#include <stdio.h>
#define UNREFERENCED_PARAMETER(P) {(P) = (P);}
int main(int argc, char **argv) {
  UNREFERENCED_PARAMETER(argc);
  puts(argv[1]);
  return 0;
}