dcm*_*m88 13 gcc clang compiler-warnings variadic-templates c++11
我一直面临的一个问题是编译器抱怨未使用的变量,即使使用了变量,但它仅用于特定实例化的参数包扩展中.例如:
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>());
Run Code Online (Sandbox Code Playgroud)
查看实例(尝试在第4行更改元组,在<>中添加一个int以查看警告消失).我知道我可以添加(void)var;一行来使警告消失,但对我来说感觉很脏,特别是当函数实际上只是一行时.我也不想在全球范围内禁用此警告,因为它确实提供了有时的洞察力.
此问题的类似表现形式是在lambda捕获中使用变量时.在这种情况下,gcc没有发出警告,而clang抱怨(我认为gcc从未实现过关于未使用的lambda捕获的警告):
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>());
Run Code Online (Sandbox Code Playgroud)
如果你可以使用C++ 17,那么[[maybe_unused]]属性是IMO最清晰的解决方案:
[[maybe_unused]]
auto tuple = get_tuple();
Run Code Online (Sandbox Code Playgroud)
var确实没有用空包装.有意吗?编译器只能猜测.
虽然clang认为比空包更具用法,但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)...);
}
Run Code Online (Sandbox Code Playgroud)
或者在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)...);
}
}
Run Code Online (Sandbox Code Playgroud)这似乎是 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)...);
}
Run Code Online (Sandbox Code Playgroud)
如果您被迫使用无法识别的编译器[[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)...);
}
Run Code Online (Sandbox Code Playgroud)