英文:
unexplained warning when using std::apply on empty tuple with msvc
问题
我在使用std::apply
在空元组上时收到了一个关于未引用变量的警告。
这个片段受到了std::apply cppreference的启发,展示了这个问题:
#include <iostream>
#include <tuple>
#include <utility>
template <typename... Ts>
std::ostream& operator<<(std::ostream& os, std::tuple<Ts...> const& theTuple) {
std::apply(
[&os](Ts const&... tupleArgs) {
os << '[';
std::size_t n{0};
((os << tupleArgs << (++n != sizeof...(Ts) ? ", " : "")), ...);
os << ']';
},
theTuple);
return os;
}
int main() {
// serialization example
std::tuple myTuple{25, "Hello", 9.31f, 'c'};
std::cout << myTuple << '\n';
std::cout << std::tuple<>() << '\n';
}
在线演示
使用/permissive-
选项的MSVC,在最后一行输出以下警告:
gcc 和 clang 不会发出任何警告。
由于我也使用了Werror
//we
,我想摆脱这个警告(如果可能的话,不使用#pragma)。
- 为什么 MSVC 的行为会这样?
- 我如何摆脱这个警告(在 lambda 内部添加
if constexpr (sizeof...(Ts)>0)
会有帮助吗?
英文:
I have a warning about unreferenced variable when using std::apply on an empty tuple.
This snippet, inspired from std::apply cppreference shows the issue:
#include <iostream>
#include <tuple>
#include <utility>
template <typename... Ts>
std::ostream& operator<<(std::ostream& os, std::tuple<Ts...> const& theTuple) {
std::apply(
[&os](Ts const&... tupleArgs) {
os << '[';
std::size_t n{0};
((os << tupleArgs << (++n != sizeof...(Ts) ? ", " : "")), ...);
os << ']';
},
theTuple);
return os;
}
int main() {
// serialization example
std::tuple myTuple{25, "Hello", 9.31f, 'c'};
std::cout << myTuple << '\n';
std::cout << std::tuple<>() << '\n';
}
Live<br>
MSVC, with /permissive-
, outputs the following warning with the very last line:
> <source>(10): warning C4189: 'n': local variable is initialized but not referenced<br>
> <source>(22): note: see reference to function template instantiation 'std::ostream &operator <<<>(std::ostream &,const std::tuple<> &)' being compiled
gcc and clangs do not issue anything.
As I'm using also Werror
//we
I'd like to get rid of this warning (without using pragma, if possible).
- Why does msvc behaves like that?
- How can I get rid of this warning (adding a
if constexpr (sizeof...(Ts)>0)
inside the lambda?)?
答案1
得分: 1
从fold expression cppreference中提出一个答案。
> 解释
...<br>
当一个一元折叠与长度为零的包扩展一起使用时,只允许以下操作符:
>
> 1) 逻辑与(&&)。空包的值为true
> 2) 逻辑或(||)。空包的值为false<br>
> 3) 逗号操作符(,)。空包的值为void()
重点在于。
因此,在 ((os << tupleArgs << (++n != sizeof...(Ts) ? ", " : "")), ...);
中,如果元组为空,则表达式变为 void();
,导致 n
未被使用,因此 msvc 正确地发出警告。
然后,可以通过简单的 [[maybe_unused]] std::size_t n{0};
来消除此警告。
可以争论地,我们也可以这样写:
#include <iostream>
#include <tuple>
#include <utility>
template <typename... Ts>
std::ostream& operator<<(std::ostream& os, std::tuple<Ts...> const& theTuple) {
std::apply(
[&os](Ts const&... tupleArgs) {
os << '[';
if constexpr (sizeof...(Ts)) {
std::size_t n{0};
((os << tupleArgs << (++n != sizeof...(Ts) ? ", " : "")), ...);
}
os << ']';
},
theTuple);
return os;
}
int main() {
// serialization example
std::tuple myTuple{25, "Hello", 9.31f, 'c'};
std::cout << myTuple << '\n';
std::cout << std::tuple<>() << '\n';
}
if constexpr
更冗长,但在 n
实际未使用时更明确。<br>
奇怪的是,我找不到一种方法来让 gcc 和 clang 发出类似的警告。
英文:
Proposing an answer from the comments.
From fold expression cppreference:
> Explanation
...<br>
When a unary fold is used with a pack expansion of length zero, only the following operators are allowed:
>
> 1) Logical AND (&&). The value for the empty pack is true
> 2) Logical OR (||). The value for the empty pack is false<br>
> 3) The comma operator (,). The value for the empty pack is void()
emphasis mine.
Thus in ((os << tupleArgs << (++n != sizeof...(Ts) ? ", " : "")), ...);
, if the tuple is empty, the expression becomes void();
, resulting to n
not being used, thus msvc is right to issue a warning.
Then, this warning can be silenced by a mere [[maybe_unused]] std::size_t n{0};
.
Arguably we could also write:
#include <iostream>
#include <tuple>
#include <utility>
template <typename... Ts>
std::ostream& operator<<(std::ostream& os, std::tuple<Ts...> const& theTuple) {
std::apply(
[&os](Ts const&... tupleArgs) {
os << '[';
if constexpr (sizeof...(Ts)) {
std::size_t n{0};
((os << tupleArgs << (++n != sizeof...(Ts) ? ", " : "")), ...);
}
os << ']';
},
theTuple);
return os;
}
int main() {
// serialization example
std::tuple myTuple{25, "Hello", 9.31f, 'c'};
std::cout << myTuple << '\n';
std::cout << std::tuple<>() << '\n';
}
The if constexpr
is more verbose but also more explicit with respect to when n
is actually unused.<br>
Strangely enough, I couldn't find a way to make gcc and clang issue a similar warning.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论