自 Visual Studio 15.6.2 编译器更新标准以来的新 C++17 [[nodiscard]] 警告是否符合标准?
Are new C++17 [[nodiscard]] warnings since Visual Studio 15.6.2 compiler update standards-compliant?
Studio 最近 Visual Studio 升级到版本 15.6.2 包括 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
我的理论是这个警告是由以下原因引起的:
- Visual C++ 根据
emplace_back
、 实现 push_back
emplace_back
在 C++17 中返回引用,并且
- 如果设置了
_HAS_CXX17
宏,后一个函数在 Visual C++ 中的实现有点奇怪(对我来说)。
但是,无论任何内部库代码如何,Visual C++ 是否都违反了生成这些诊断消息的标准? wandbox.org 的最新 Clang 和 GCC 版本不会对相同的代码产生任何警告。
我坚持认为 nodiscard
用户类型(如 S
的库内部用法永远不会引起警告,因为这会使该功能在实践中无法使用,但是 [=25= 的简短描述] 在 §10.6.7/2 [dcl.attr.nodiscard] 中对该主题有点含糊。
或者标准只是 "discourage" 这样的警告,这确实是一个 QoI 问题,尽管在这种情况下是一个相当严重的问题,严重到可能应该作为错误报告提交给 Microsoft ?
这是完整的警告:
C:\Program Files (x86)\Microsoft Visual Studio17\Community\VC\Tools\MSVC.13.26128\include\vector(996): warning C4834: discarding return value of function with 'nodiscard' attribute
C:\Program Files (x86)\Microsoft Visual Studio17\Community\VC\Tools\MSVC.13.26128\include\vector(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 Studio17\Community\VC\Tools\MSVC.13.26128\include\vector(1934): warning C4834: discarding return value of function with 'nodiscard' attribute
C:\Program Files (x86)\Microsoft Visual Studio17\Community\VC\Tools\MSVC.13.26128\include\vector(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 Studio17\Community\VC\Tools\MSVC.13.26128\include\vector(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
]
However, regardless of any internal library code, doesn't Visual C++ violate the standard in producing those diagnostic messages?
这个问题真的没有意义。该标准规定,如果程序违反可诊断规则,则实现必须发出诊断。该标准没有说明禁止对其他 well-formed 程序进行诊断。
有很多很多常见的编译器警告是对 well-formed 代码的诊断。这太棒了!确保您收到的警告是有价值的,这确实是一个实施质量问题。在这种情况下,这显然不是有价值的警告,因此您应该向 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
Studio 最近 Visual Studio 升级到版本 15.6.2 包括 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
我的理论是这个警告是由以下原因引起的:
- Visual C++ 根据
emplace_back
、 实现 emplace_back
在 C++17 中返回引用,并且- 如果设置了
_HAS_CXX17
宏,后一个函数在 Visual C++ 中的实现有点奇怪(对我来说)。
push_back
但是,无论任何内部库代码如何,Visual C++ 是否都违反了生成这些诊断消息的标准? wandbox.org 的最新 Clang 和 GCC 版本不会对相同的代码产生任何警告。
我坚持认为 nodiscard
用户类型(如 S
的库内部用法永远不会引起警告,因为这会使该功能在实践中无法使用,但是 [=25= 的简短描述] 在 §10.6.7/2 [dcl.attr.nodiscard] 中对该主题有点含糊。
或者标准只是 "discourage" 这样的警告,这确实是一个 QoI 问题,尽管在这种情况下是一个相当严重的问题,严重到可能应该作为错误报告提交给 Microsoft ?
这是完整的警告:
C:\Program Files (x86)\Microsoft Visual Studio17\Community\VC\Tools\MSVC.13.26128\include\vector(996): warning C4834: discarding return value of function with 'nodiscard' attribute
C:\Program Files (x86)\Microsoft Visual Studio17\Community\VC\Tools\MSVC.13.26128\include\vector(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 Studio17\Community\VC\Tools\MSVC.13.26128\include\vector(1934): warning C4834: discarding return value of function with 'nodiscard' attribute
C:\Program Files (x86)\Microsoft Visual Studio17\Community\VC\Tools\MSVC.13.26128\include\vector(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 Studio17\Community\VC\Tools\MSVC.13.26128\include\vector(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
]
However, regardless of any internal library code, doesn't Visual C++ violate the standard in producing those diagnostic messages?
这个问题真的没有意义。该标准规定,如果程序违反可诊断规则,则实现必须发出诊断。该标准没有说明禁止对其他 well-formed 程序进行诊断。
有很多很多常见的编译器警告是对 well-formed 代码的诊断。这太棒了!确保您收到的警告是有价值的,这确实是一个实施质量问题。在这种情况下,这显然不是有价值的警告,因此您应该向 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