为啥 VS 不为逻辑运算符定义替代标记?
Posted
技术标签:
【中文标题】为啥 VS 不为逻辑运算符定义替代标记?【英文标题】:Why does VS not define the alternative tokens for logical operators?为什么 VS 不为逻辑运算符定义替代标记? 【发布时间】:2014-06-25 16:33:46 【问题描述】:替代标记是 valid c++ keywords,但在 Visual Studio 2013 中会发出编译错误(未声明的标识符):
int main(int argc, const char* argv[])
int k(1), l(2);
if (k and l) cout << "both non zero\n";
return 0;
and or not
已经存在很长时间了,是否有理由不实施它们?
【问题讨论】:
错误信息是什么究竟? 我想知道为什么会这样。这不可能是实现的复杂性,如果他们害怕破坏旧代码,同样应该适用于 gcc 等。一个简单的 grep/replace 就可以解决他们的任何代码库冲突,那么是否有更深层次的原因,是幕后有争议还是只是一个没人关心的功能? @NikosAthanasiou 一个简单的 grep/replace 可能会搞砸很多 cmets。 GCC 通常比 MSVC 在以符合标准的名义破坏旧代码方面更多更随意。 【参考方案1】:您询问原因。这是一个可能的原因,不一定是对 Visual C++ 团队影响最大的原因:
-
这些是 C 中的有效标识符。
长期以来,Microsoft 的建议是对 C 和 C++ 代码都使用 C++ 模式,而不是维护现代 C 编译器。
使用这些作为标识符的有效 C 代码如果被编译为关键字,将会无缘无故地中断。
尝试编写可移植 C++ 的人大多使用
/permissive-
或 /Za
以获得最大的一致性,这将导致这些被视为关键字。
通过包含头文件将它们视为/Ze
中的关键字的解决方法既简单又可移植。 (G++ 的解决方法-fno-operator-names
也不错,但是将选项放在源代码中而不是构建系统中会更好一些。)
【讨论】:
能否修改/Za
部分,好吗?显然它有很多错误,微软不鼓励使用它(当然,grrr 不在文档中)。见reddit.com/r/cpp/comments/76pmky/til_c_has_and_or_and_not/…
另外请注意,/Za
会导致 MSVC 中出现错误,当包含windows.h
时会触发编译器错误。我在查看此帖子后遇到此问题,因此对此进行了报告:github.com/SasLuca/MSVCBug/blob/master/README.md
如果您遇到/Za
的问题,请改用/permissive-
。【参考方案2】:
VS 不合格。这是旧闻。
要使用替代标记,请包含 <ciso646>
标头。根据标准,包含此标头应该在 C++ 中无效。但是,您在 VS 中确实需要它。因此,只要有可能使用 VS 进行编译,始终包含它是安全的。
【讨论】:
正如已经指出的,这种“不符合”仅特定于默认编译设置。大多数(如果不是全部)编译器在默认模式下不符合标准。指定/Za
选项会从 VS 编译器中删除这种不符合项。
gcc 与 C++11 或更高版本没有 -pthreads 选项是另一个很好的例子。【参考方案3】:
形式上,这些关键字 被编译器实现并在本质上得到支持,而不包括任何头文件。但是,为此,您必须在 C++ 编译器的“更标准”模式下编译源代码,这意味着使用 /Za
选项。
根据意图,/Za
选项应该“禁用编译器扩展”。当然,不支持兼容编译器中应该存在的东西不能正式限定为“编译器扩展”。然而,这正是目前的情况。
【讨论】:
不回答“为什么?”的问题 @Ben Voigt:嗯,它认为“为什么”部分来自“为什么不实施?”。这样的问题是基于一个不正确的前提,因为它们实际上已经实现了。 “扩展”是让程序员将这些名称作为标识符。 @Ben Voigt:是的,但是“扩展”的正式定义明确表示不允许扩展破坏任何合规代码。换句话说,真正的扩展允许“定义标准未定义的内容”,但不允许“取消定义(或重新定义)标准已经定义的内容”。形式上,允许扩展extend可编译代码的域,但不允许收缩它。 遗憾的是,这对我来说实际上不是一个选项,因为它会导致标准标题中出现很多错误,例如winnt.h(12723): error C2467: illegal declaration of anonymous 'struct'
。【参考方案4】:
现代 Visual Studio(或者更确切地说,MSVC)确实支持替代令牌;但是,它只在standards conformance mode 中这样做。这种模式有很多好处,所以应该一直使用它。
要启用它,请将/permissive-
传递给编译器。
以下答案已过时。现在支持,见上文!
以前,Microsoft’s position was1 那个
#include
的<iso646.h>
(或ciso646
)是我们支持这些关键字的方式
因为“没有人”(在我之前,2007 年)曾经要求过这个。
1 链接目前已失效;留在这里存档。
【讨论】:
【参考方案5】:(当代更新)
我做了一个小测试:一个新的“Windows 桌面应用程序”项目。 IDE (Visual Studio 2017 15.7.5) 默认设置以下 C++ 语言一致性设置:/permissive- /Zc:wchar_t /Zc:forScope /Zc:inline。此外,我将 C++ 语言标准 设置为 ISO C++ /最新草案(目前最高为 C++ 17).此外,我在 main() 中添加了以下 2 行:
bool a, b, c;
a = b and c;
它成功地编译了逻辑运算符的文本形式。但是当我将 IDE Conformance mode 更改为 No (=> without /permissive -) 并重新编译,编译器标记:“error C2065: 'and': undeclared identifier”。
默认情况下,/permissive- 编译器选项设置在由 Visual Studio 2017 版本 15.5(2017 年 12 月)及更高版本创建的新项目中。在早期版本中默认未设置。因此,如果有人在 15.5 版本之前创建了一个项目,并且在将 IDE 更新到最新版本时,仍然需要在项目中手动设置此编译器选项。
/Ze 编译器选项(默认启用)启用 Microsoft 扩展。 /Ze 选项已被弃用,因为它的行为默认为开启。 MSDN 建议使用 /Zc(一致性)编译器选项来控制特定的语言扩展功能。
【讨论】:
以上是关于为啥 VS 不为逻辑运算符定义替代标记?的主要内容,如果未能解决你的问题,请参考以下文章