如何处理空模板参数包扩展引起的未使用的警告?
即使使用了变量,我仍然面临的一个问题是编译器会抱怨一个未使用的变量,但它只用于参数包扩展中,对于特定的实例而言,它只是空的。 例如:如何处理空模板参数包扩展引起的未使用的警告?
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>());
参见live example(尝试改变元组在第4行中,加入内<一个int>看到警告消失)。 我知道我可以添加一条(void)var;
行来使警告消失,但对我来说感觉很脏,特别是当函数实际上只是一行时。 我也不想全局禁用此警告,因为它有时会提供洞察力。
这个问题的一个类似的表现是变量用于lambda捕获。在这种情况下,海湾合作委员会吐出任何警告,而铛抱怨(我想不用的拉姆达捕捉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>());
这似乎是在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)...);
}
这种破坏可移植性吗? –
如果某个属性无法识别,编译器会忽略它。 GCC和LLVM都支持'[[gnu :: unused]]'。 –
不会识别的属性也会吐出警告吗? [像这样](https://godbolt.org/g/oz9cwR) –
也许有是其他问题,但是...根据您在编译器资源管理器中链接的代码,您的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
是使用(潜在的)和,如你观察到的,警告消失。
但是如果'var'是空的,代码扩展为空,不是吗? – Rakete1111
@ Rakete1111 - 我想你是对的,但(如果我没有错)'var'永远不会被使用;当'sizeof ...(I)'为零时,何时磨碎。所以警告信息。当OP在'std :: tuple
同意,代码使用'var',所以警告是错误的。不知道我理解你的最后一点。 – Rakete1111
(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;
具有零度运行时间的影响。
如果你可以使用C++ 17的[[maybe_unused]]
属性是IMO清晰的解决方案:
[[maybe_unused]]
auto tuple = get_tuple();
当变量在lambda中时,你将如何使用它capture:https://godbolt.org/g/CrwNhM – dcmm88
@ dcmm88提交错误,因为你正在使用'var'。这是一个解决方法:https://godbolt.org/g/xLzKnB – Rakete1111
var
的确不是空包使用。 它是打算?编译器只能猜测。
鉴于锵比空包是一种用法,gcc选择相反。
您可以静默以不同的方式作为警告:
- 属性
[[maybe_unused]]
(C++ 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)...); }
或C++ 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)...); } }
C风格强制转换为void是C风格强制转换可能不会做坏行为的少数情况之一。另外,'unused_var'可能会无意中强迫ODR存在一个变量。 – Yakk
使用铛和文件到GCC的bug报告:P – Rakete1111
您仍然可以'编译推/ pop'围绕该功能禁用警告。但'static_cast(var);'似乎更好的解决方法。 –
Jarod42
'return func2(std :: get (get_tuple())...);'? – nwp