自 Visual Studio 15.6.2 编译器更新以来的新 C++17 [[nodiscard]] 警告是否符合标



最近升级到版本15.6.2的Visual Studio Studio包括Visual C++编译器更新,由于[[nodiscard]],该更新导致push_back行出现以下代码警告:

#include <vector>
struct [[nodiscard]] S
{
int i;
};
int main()
{
std::vector<S> v;
v.push_back({ 1 }); // causes warning C4834
}

编译器的调用方式如下(请注意,无需指定高警告级别即可重现,但需要/std:c++latest,并且/permissive-是可选的):

cl /nologo /EHsc /permissive- /std:c++latest test.cpp

警告来自Visual C++自己的std::vector实现代码中,并说:

warning C4834: discarding return value of function with 'nodiscard' attribute

(有关完整的警告输出,请参见下文)

编译器版本:

Microsoft (R) C/C++ Optimizing Compiler Version 19.13.26128 for x64

我的理论是,这个警告是由以下原因引起的:

  1. 视觉C++在emplace_back方面实现push_back
  2. emplace_back返回 C++17 中的引用,并且
  3. 如果设置了_HAS_CXX17宏,则在Visual C++中对后一个函数的实现有点好奇(对我来说)。

但是,无论任何内部库代码如何,Visual C++ 在生成这些诊断消息时不会违反标准吗?最新的 Clang 和 GCC 版本 wandbox.org 不会为相同的代码生成任何警告。

我坚持认为,像S这样的nodiscard用户类型的库内部用法永远不会引起警告,因为这会使该功能在实践中无法使用,但是§10.6.7/2 [dcl.attr.nodiscard]中对nodiscard的简短描述在这个主题上有点模糊。

还是标准只是"阻止"此类警告,这确实是一个 QoI 问题,尽管在这种情况下是一个相当严重的问题,严重到可能应该在 Microsoft 上作为错误报告提交?


以下是完整的警告:

C:Program Files (x86)Microsoft Visual Studio2017CommunityVCToolsMSVC14.13.26128includevector(996): warning C4834: discarding return value of function with 'nodiscard' attribute
C:Program Files (x86)Microsoft Visual Studio2017CommunityVCToolsMSVC14.13.26128includevector(995): note: while compiling class template member function 'void std::vector<S,std::allocator<_Ty>>::push_back(_Ty &&)'
with
[
_Ty=S
]
test.cpp(11): note: see reference to function template instantiation 'void std::vector<S,std::allocator<_Ty>>::push_back(_Ty &&)' being compiled
with
[
_Ty=S
]
test.cpp(10): note: see reference to class template instantiation 'std::vector<S,std::allocator<_Ty>>' being compiled
with
[
_Ty=S
]
C:Program Files (x86)Microsoft Visual Studio2017CommunityVCToolsMSVC14.13.26128includevector(1934): warning C4834: discarding return value of function with 'nodiscard' attribute
C:Program Files (x86)Microsoft Visual Studio2017CommunityVCToolsMSVC14.13.26128includevector(1933): note: while compiling class template member function 'void std::vector<S,std::allocator<_Ty>>::_Umove_if_noexcept1(S *,S *,S *,std::true_type)'
with
[
_Ty=S
]
C:Program Files (x86)Microsoft Visual Studio2017CommunityVCToolsMSVC14.13.26128includevector(1944): note: see reference to function template instantiation 'void std::vector<S,std::allocator<_Ty>>::_Umove_if_noexcept1(S *,S *,S *,std::true_type)' being compiled
with
[
_Ty=S
]

但是,无论任何内部库代码如何,Visual C++ 在生成这些诊断消息时不会违反标准吗?

这个问题真的没有意义。该标准规定,如果程序违反可诊断规则,则实现必须发出诊断。该标准没有说明不允许对其他格式良好的程序进行诊断。

有许多常见的编译器警告是对格式正确的代码的诊断。太好了!这确实是一个实现质量问题,以确保您收到的警告是有价值的。在这种情况下,这显然不是一个有价值的警告,因此您应该向Microsoft提交错误报告。但这并不是因为此警告违反了标准 - 仅仅是因为它不是一个有用的警告。

从技术上讲,这不是 MSVC 错误,但是在标准中不鼓励对引用类型[[nodiscard]]警告,而不是禁止。

根据我们的对话,这是一个重现示例:

struct [[nodiscard]] S{ int i;};
template<class T>
T& return_self(T& _in){
return _in;
}
int main() {
S s{1};
return_self(s);
}

C++标准有一个非常相似的例子,他们不鼓励引发警告([dcl.attr.nodiscard]):

struct [[nodiscard]] error_info { /* ... */ };
error_info &foo();
void f() { foo(); } // warning not encouraged: not a nodiscard call, because neither
// the (reference) return type nor the function is declared nodiscard

最新更新