Это хороший подход к использованию 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;
}
В таком случае просто не пишите имя переменной:
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. Поэтому, когда приложение завершается, вызывается деструктор, который может выполнить деинициализацию.
Обратите внимание, что компилятор знает, что классы могут делать что-то полезное в конструкторе и деструкторе, поэтому он не будет жаловаться на неиспользуемую переменную.
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
объявленные переменные.
станд :: игнорировать не предназначался для использования с этой целью:
Объект неопределенного типа, так что ему может быть присвоено любое значение без эффекта. Предназначен для использования с std :: tie при распаковке std :: tuple, в качестве заполнителя для аргументов, которые не используются.
Я бы предложил тебе не делайте то, что вы думаете, поскольку в реальном большом проекте это приведет к тому, что код будет сложнее поддерживать, где можно было бы посмотреть на прототип функции, увидеть, что он принимает аргумент 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 () {}
Больше руды, меньше тех же преимуществ.