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 () {}
больше руды меньше таких же преимуществ.