В c ++ 03 и ранее, чтобы отключить предупреждение компилятора о неиспользуемом параметре, я обычно использую такой код:
#define UNUSED(expr) do { (void)(expr); } while (0)
Например
int main(int argc, char *argv[])
{
UNUSED(argc);
UNUSED(argv);
return 0;
}
Но макросы - не лучшая практика для C ++, поэтому. Есть ли лучшее решение в стандарте С ++ 11? Я имею в виду, могу ли я избавиться от макросов?
Спасибо за все!
c++
c++11
unused-variables
Inkooboo
источник
источник
(void)argc;
короче и яснее, чемUNUSED(argc);
unused(argc, argv)
сtemplate<class... T> void unused(T&&...){}
. Понятно, лаконично и без макросов.void foo(int /*unused_arg*/, int used_arg)
Ответы:
Для этой цели я использовал функцию с пустым телом:
template <typename T> void ignore(T &&) { } void f(int a, int b) { ignore(a); ignore(b); return; }
Я ожидаю, что любой серьезный компилятор оптимизирует вызов функции и заглушит предупреждения для меня.
источник
T
- параметр шаблона,T&&
это универсальная ссылка, которая привязана к чему угодно.Вы можете просто опустить имена параметров:
int main(int, char *[]) { return 0; }
А в случае с main можно вообще не указывать параметры:
int main() { // no return implies return 0; }
См. «§ 3.6 Начало и завершение» в стандарте C ++ 11.
источник
main
, вы можете вообще опустить параметры. Иreturn
заявление, если на то пошло.main
«sreturn 0
в TestCase, но почти всегда писать самодокументируемыйreturn EXIT_SUCCESS
в производстве код. Это хорошая практика!Существует
<tuple>
в C ++ 11 , который включает в себя готовые к использованиюstd::ignore
объекта, которые позволяют нам писать (очень вероятно , не накладывая во время выполнения накладных расходов):void f(int x) { std::ignore = x; }
источник
Чтобы «отключить» это предупреждение, лучше всего не писать аргумент, просто укажите тип.
void function( int, int ) { }
или, если хотите, закомментируйте:
void function( int /*a*/, int /*b*/ ) { }
Вы можете смешивать именованные и безымянные аргументы:
void function( int a, int /*b*/ ) { }
В C ++ 17 есть спецификатор атрибута [[might_unused]], например:
void function( [[maybe_unused]] int a, [[maybe_unused]] int b ) { }
источник
/* ... */
#if 0
как особый случай, даже если они не поддерживают полный intellisense препроцессора.Ничего подобного, нет.
Итак, вы застряли на тех же старых вариантах. Вы счастливы полностью опустить имена в списке параметров?
int main(int, char**)
В конкретном случае
main
, конечно, вы можете просто опустить сами параметры:int main()
Есть также типичные уловки, зависящие от реализации, такие как GCC
__attribute__((unused))
.источник
Макросы могут быть не идеальными, но они хорошо справляются с этой задачей. Я бы сказал, придерживайтесь макроса.
источник
MAYBE_UNUSED
этой причине я бы назвал макрос ; Обычно меня не волнует, сказал ли я «не волнуйтесь, если я не воспользуюсь этим ниже», но все равно продолжу это делать.Что вы имеете против старого и стандартного пути?
void f(int a, int b) { (void)a; (void)b; return; }
источник
Нет ничего нового.
Для меня лучше всего закомментировать имя параметра в реализации. Таким образом, вы избавитесь от предупреждения, но при этом сохраните некоторое представление о том, что это за параметр (поскольку имя доступно).
У вашего макроса (и любого другого подхода с приведением к пустоте) есть обратная сторона: вы действительно можете использовать параметр после использования макроса. Это может усложнить сопровождение кода.
источник
Заголовок Boost
<boost/core/ignore_unused.hpp>
(Boost> = 1.56) определяет для этой цели шаблон функции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 имеет
[[maybe_unused]]
атрибут подавления предупреждений о неиспользуемых объектах.источник
[[maybe_unused]]
это явный способ, в настоящее время лучший.Мне очень нравится использовать для этого макросы, потому что они позволяют лучше контролировать, когда у вас есть разные отладочные сборки (например, если вы хотите создавать с включенными утверждениями):
#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
а затем используйте его как:
int myFunc(int myInt, float MY_USED_FOR_ASSERTS(myFloat), char MY_UNUSED(myChar)) { MY_ASSERT(myChar < 12.0f); return myInt; }
источник
У меня есть собственная реализация для критических по времени сегментов кода. Я некоторое время исследовал критический по времени код для замедления и обнаружил, что эта реализация потребляет около 2% от критического по времени кода, который я оптимизирую:
#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
Критический по времени код использовал
ASSERT*
определения для целей отладки, но в выпуске он явно вырезан, но ... Кажется, этот код производит немного более быстрый код в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)
Причина в двойном
false ?
выражении. Он каким-то образом производит немного более быстрый код в выпуске с максимальной оптимизацией.Я не знаю, почему это быстрее (кажется ошибкой при оптимизации компилятора), но это, по крайней мере, лучшее решение для этого случая кода.
Примечание . Важнее всего то, что критичный по времени код замедляется без утверждений выше или неиспользуемых макросов в выпуске. Другими словами, двойное
false ?
выражение на удивление помогает оптимизировать код.источник
windows.h определяет UNREFERENCED_PARAMETER :
#define UNREFERENCED_PARAMETER(P) {(P) = (P);}
Итак, вы могли бы сделать это так:
#include <windows.h> #include <stdio.h> int main(int argc, char **argv) { UNREFERENCED_PARAMETER(argc); puts(argv[1]); return 0; }
Или вне Windows:
#include <stdio.h> #define UNREFERENCED_PARAMETER(P) {(P) = (P);} int main(int argc, char **argv) { UNREFERENCED_PARAMETER(argc); puts(argv[1]); return 0; }
источник
operator=
могут возникнуть побочные эффекты.