std :: ignore для игнорирования неиспользуемой переменной

Это хороший подход к использованию std::ignore для игнорирования неиспользуемых переменных?

Предположим, у меня есть такая функция:

void func(int i)
{
//for some reason, I don't need i anymore but I cannot change signature of function
std::ignore = i;
}

Дополнительная информация

Это был один пример, и некоторые ответы предложили использовать анонимный переменные. Но как бы я сделал это для других случаев, таких как:

int Thread_UnSafe_func_returnSomething():
void func()
{
// To make it thread safe
// Also it is required to call only once
static int i = Thread_UnSafe_func_returnSomething();

std::ignore = i;
}

32

Решение

В таком случае просто не пишите имя переменной:

void func(int /*i*/)
{
...
}

Ответ @ Хейта хорош, но использует последнюю версию C ++, которая не всегда доступна. Не писать имя переменной — это старое соглашение, сообщающее компилятору, что переменная вам на самом деле не нужна.

Для обновленного вопроса я бы пошел на статический экземпляр класса с необходимой инициализацией в конструкторе. Я говорю инициализация, потому что единственная причина, по которой я могу сделать такую ​​функцию, — это инициализация некоторого глобального объекта.

class SomethingInitializer {
public:
SomethingInitializer() {
func_returnSomething();
}
~SomethingInitializer() {
// Note, that when you initialize something it is a good practice to deinitialize it at the end, and here is a proper place for that.
}
};

void func() {
static SomethingInitializer initializer;
}

Это решение имеет небольшой бонус: SomethingInitializer соответствует RAII. Поэтому, когда приложение завершается, вызывается деструктор, который может выполнить деинициализацию.

Обратите внимание, что компилятор знает, что классы могут делать что-то полезное в конструкторе и деструкторе, поэтому он не будет жаловаться на неиспользуемую переменную.

40

Другие решения

std::ignore может работать, но он предназначен для кортежей. Таким образом, вам нужно включить заголовок кортежа, и кто знает, какие операции выполняются для назначения. Это также может сломаться в другой версии C ++, потому что она никогда не была документирована для использования таким образом.

Лучшим способом для этого является атрибут C ++ 17 [[maybe_unused]]

void func([[maybe_unused]] int i)
{
}

Он размещает объявление прямо в объявлении переменной, поэтому вам не нужно объявлять его в дополнительной строке / выражении.

То же самое можно использовать для локальных (и локально-статических) переменных.

...
[[maybe_unused]] static int a = something();
...

А также для многих других:

Появляется в объявлении класса, typedef, переменной,
нестатический член данных, функция, перечисление или перечислитель.
Если компилятор выдает предупреждения о неиспользуемых объектах, это предупреждение
подавлено для любого объекта, объявленного Maybe_unused.

Увидеть http://en.cppreference.com/w/cpp/language/attributes

Что касается людей, обеспокоенных тем, что вы все еще можете использовать переменные после того, как объявите их неиспользованными:

Да, это возможно, но (по крайней мере, с помощью clang) вы получите предупреждения в случае использования maybe_unused объявленные переменные.

35

станд :: игнорировать не предназначался для использования с этой целью:

Объект неопределенного типа, так что ему может быть присвоено любое значение без эффекта. Предназначен для использования с std :: tie при распаковке std :: tuple, в качестве заполнителя для аргументов, которые не используются.


Я бы предложил тебе не делайте то, что вы думаете, поскольку в реальном большом проекте это приведет к тому, что код будет сложнее поддерживать, где можно было бы посмотреть на прототип функции, увидеть, что он принимает аргумент int i, но функция не нуждается в этом на самом деле — не чувствует себя хорошо, не так ли? 🙂

15

Как альтернатива, без удаления i Исходя из подписи (как может потребоваться некоторым инструментам документации), есть несколько способов сделать предупреждение молчанием:

void func(int i)
{
static_cast<void>(i); // Silent warning for unused variable
}

Он не является полностью переносимым, но это предупреждает большинство компиляторов.

Чистый способ — создать для этого отдельную функцию:

template <typename T>
void Unused(T&& /*No name*/) { /*Empty*/ }

а потом

void func(int i)
{
Unused(i); // Silent warning for unused variable
}
8

Я думаю, что у вас есть проблема XY здесь. Вы действительно не заботитесь о том, как игнорировать статические переменные; Вы просто хотите вызвать функцию один раз (и только один раз) потокобезопасным, реентерабельным способом.

На что я говорю: вы слышали о std::call_once? Вы должны переписать свой метод как

#include <mutex>

int Thread_UnSafe_func_returnSomething();
void func(void)
{
//To make it thread safe
static std::once_flag initComplete;
std::call_once(initComplete, func_returnSomething);
}
2

Другой способ сделать это с помощью конечного типа возвращаемого значения:

auto func(int i) -> decltype(void(i)) {}
int main() {}

Если у вас есть более одной переменной, вы можете перечислить их все:

auto func(int i, int j) -> decltype(void(i), void(j)) {}
int main() {}

И вы все равно можете объявить предпочитаемый тип возврата, если void это не то что ты хочешь

auto func(int i) -> decltype(void(i), int{}) { return 42; }
int main() {}

Преимущества этого решения:

  • Имя переменной сохраняется: как уже упоминалось другими, не давать имя переменной не может быть вариантом (из-за вашей системы документации, в качестве примера).

  • Вы не будете загрязнять свое функциональное тело бесполезными выражениями, направленными на то, чтобы замолчать несколько предупреждений.

  • Вам не нужно явно определять функцию поддержки, чтобы сделать это.

Конечно, это не относится к статическим переменным, объявленным в теле функции, но вы можете сделать нечто подобное при возврате из функции (просто пример):

int f() {
static int i = 0;
static int j = 0;
return void(i), void(j), 42;
}

int main () {}

Больше руды, меньше тех же преимуществ.

1
По вопросам рекламы [email protected]