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

Chr*_*ckl 4 c++ visual-c++ language-lawyer c++17

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

#include <vector>

struct [[nodiscard]] S
{
    int i;
};

int main()
{
    std::vector<S> v;
    v.push_back({ 1 }); // causes warning C4834
}
Run Code Online (Sandbox Code Playgroud)

编译器是这样调用的(注意不需要指定高警告级别来重现,但这/std:c++latest是必需的,并且/permissive-是可选的):

#include <vector>

struct [[nodiscard]] S
{
    int i;
};

int main()
{
    std::vector<S> v;
    v.push_back({ 1 }); // causes warning C4834
}
Run Code Online (Sandbox Code Playgroud)

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

cl /nologo /EHsc /permissive- /std:c++latest test.cpp
Run Code Online (Sandbox Code Playgroud)

(完整的警告输出见下文)

编译器版本:

warning C4834: discarding return value of function with 'nodiscard' attribute
Run Code Online (Sandbox Code Playgroud)

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

  1. VISUAL C ++实现push_back来讲emplace_back
  2. emplace_back 在 C++17 中返回一个引用,以及
  3. 如果_HAS_CXX17设置了宏,那么在 Visual C++ 中对后一个函数的实现有点好奇(对我来说)。

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

我坚持认为nodiscard用户类型的库内部使用S不应该引起警告,因为这会使该功能在实践中无法使用,但是nodiscard§10.6.7/2 [dcl.attr.nodiscard] 中的简短描述在那个话题。

或者标准是否只是简单地“劝阻”这样的警告,而这确实是一个 QoI 问题,尽管在这种情况下是一个相当严重的问题,严重到可能应该作为错误报告提交给 Microsoft?


这是完整的警告:

Microsoft (R) C/C++ Optimizing Compiler Version 19.13.26128 for x64
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 6

但是,无论任何内部库代码如何,Visual C++ 是否都违反了生成这些诊断消息的标准?

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

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

  • 在此处提交错误报告:https://developercommunity.visualstudio.com/content/problem/217312/c17-nodiscard-warnings-from-library-code.html。与往常一样,愚蠢的 Visual Studio 报告表单弄乱了一些代码格式,即使它在编辑窗口中正确显示,我也不知道如何修复它。我上次就该主题寻求帮助的请求被忽略了。哦,好吧,让我们看看它是否完成了任何事情。 (3认同)