我一直面临的问题是编译器抱怨未使用的变量,即使使用了该变量,但它仅用于特定实例化的参数包扩展中。 例如:
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&lt;&gt;以查看警告消失)。
我知道我可以添加(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>());
答案 0 :(得分:7)
如果你可以使用C ++ 17,那么[[maybe_unused]]
属性是IMO最清晰的解决方案:
[[maybe_unused]]
auto tuple = get_tuple();
答案 1 :(得分:5)
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)...);
}
或在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)...);
}
}
答案 2 :(得分:3)
这似乎是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)...);
}
答案 3 :(得分:2)
(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;
没有运行时效果。
答案 4 :(得分:-1)
也许还有其他问题但是...根据您在编译器资源管理器中链接的代码,您的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
,因此for i in enumerate(s1):
c1 = int(s1[i] < 0)
c2 = int(s1[i]>s2[i])
s3[i] = c1*0 + int(not c1)*( s1[i]*c2 + s2[i]*(not c2) )
是(可能)如你所见,警告消失了。