Ответ 1
Если вы можете использовать С++ 17, атрибут [[maybe_unused]]
является самым ясным решением IMO:
[[maybe_unused]]
auto tuple = get_tuple();
Проблема, с которой я сталкиваюсь, - это то, где компилятор жалуется на неиспользуемую переменную, даже если эта переменная используется, но она используется только в расширении пакета параметров, которое бывает пустым для конкретного экземпляра. Например:
template <std::size_t... I>
auto func1(std::index_sequence<I...>)
{
auto var = get_tuple();
return func2(std::get<I>(var)...);
}
auto a = func1(std::make_index_sequence<0>());
См. живой пример (попробуйте изменить кортеж в строке 4, добавив int внутри < > , чтобы увидеть предупреждение).
Я знаю, что я мог бы добавить строку (void)var;
, чтобы предупреждение исчезло, но мне кажется, что это грязно, особенно когда функция на самом деле представляет собой только одну строку.
Я также не хочу отключать это предупреждение во всем мире, потому что он иногда дает представление.
Аналогичное проявление этой проблемы заключается в том, когда переменная используется в лямбда-захвате. В этом случае gcc не дает никакого предупреждения, в то время как clang жалуется (я думаю, gcc никогда не реализовал предупреждение о неиспользуемых лямбда-захватах):
template <std::size_t... I>
auto func1(std::index_sequence<I...>)
{
auto var = get_tuple();
auto my_lambda = [var](){
return func2(std::get<I>(var)...);
};
return my_lambda();
}
auto a = func1(std::make_index_sequence<0>());
Если вы можете использовать С++ 17, атрибут [[maybe_unused]]
является самым ясным решением IMO:
[[maybe_unused]]
auto tuple = get_tuple();
var
действительно не используется с пустым пакетом.
Это предназначено? компилятор может только догадываться.
В то время как clang считает, что пустой пакет является использованием, gcc выбирает противоположное.
Вы можете отключить предупреждение по-разному:
[[maybe_unused]]
(С++ 17)void
(static_cast<void>(arg)
)template <typename T> void unused_var(T&&){}
, а затем unused_var(var)
).создание перегрузок:
auto func1(std::index_sequence<>)
{
return func2();
}
template <std::size_t... I>
auto func1(std::index_sequence<I...>)
{
auto var = get_tuple();
return func2(std::get<I>(var)...);
}
или в С++ 17
template <std::size_t... I>
auto func1(std::index_sequence<I...>)
{
if constexpr (sizeof ...(I) == 0) {
return func2();
} else {
auto var = get_tuple();
return func2(std::get<I>(var)...);
}
}
Это похоже на ошибку компилятора в GCC. Самое легкое обходное решение - отметить var
с помощью [[gnu::unused]]
:
template <std::size_t... I>
auto func1(std::index_sequence<I...>)
{
auto var [[gnu::unused]] = get_tuple();
return func2(std::get<I>(var)...);
}
Если вы вынуждены использовать компиляторы, которые не распознают [[gnu::unused]]
, вы можете подделать эту переменную с помощью static_cast<void>
:
template <std::size_t... I>
auto func1(std::index_sequence<I...>)
{
auto var = get_tuple();
static_cast<void>(var);
return func2(std::get<I>(var)...);
}
(void)var;
подавлено неиспользованные предупреждения в каждом компиляторе, который я использовал:
template <std::size_t... I>
auto func1(std::index_sequence<I...>)
{
auto var = get_tuple();
(void)var;
return func2(std::get<I>(var)...);
}
auto a = func1(std::make_index_sequence<0>());
(void)variable;
имеет нулевые эффекты времени выполнения.
Возможно, есть другие проблемы, но... согласно коду, который вы связали в проводнике компилятора, ваш var
является std::tuple<>
; то есть std::tuple
с нулевыми компонентами.
Если я не ошибаюсь, std::get<Num>(std::tuple<Ts..>)
определяется только тогда, когда Num
находится в [0,sizeof...(Ts))
; в этом случае в [0, 0)
, то есть пустой интервал.
Я полагаю, что ваш код (когда var
определяется как std::tuple<>
) плохо сформирован. Поэтому я полагаю, что предупреждение правильное (потому что не существует случаев, когда используется var
), но не предупреждает о реальной проблеме.
Он отличается, когда var
определяется как std::tuple<int>
: var
корректно используется, когда все I
равны нулю, поэтому var
используется (потенциально) и, как вы заметили, предупреждение исчезает.