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;
}

6 ответов


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

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

ответ@Hayt хорош, но использует последнюю версию 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. Поэтому, когда приложение завершает работу, вызывается деструктор, и он может сделать деинициализацию.

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


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

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

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

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

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

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

, а также для многого другого:

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

посмотреть http://en.cppreference.com/w/cpp/language/attributes

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

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


std:: ignore не предназначалось для использования в этих целях:

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


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


в качестве альтернативы, без удаления 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
}

Я думаю, что у вас есть проблема 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);
 }

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

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 () {}

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