如何以编程方式获取VS2017 Update8.2中/ permissve-设置的所有编译器标志

时间:2018-11-27 12:00:14

标签: c++ compiler-errors visual-studio-2017

如何以编程方式获取由Visual Studio 2017编译器标志/ permissive-

启用的选项

根据Microsoft文档/ permissive-标志设置/ Zc编译器选项以实现严格一致性

现在下面的代码在仅启用/ permissive-编译器标志的Visual Studio 2017 Update8.2上进行编译,并且在未启用/ permissive-标志的情况下失败(在Vs2017 Update 8.2上)

#include <sstream>

namespace ABC {

template <typename T>

bool operator|(T v1, T v2) {
}}

std::stringstream ss_; //commenting this removes the error

using namespace ABC;

int main() {
return 0;
}

我想知道/ Zc的哪个编译器标志已修复

1 个答案:

答案 0 :(得分:0)

在没有/permissive-的情况下会发生此问题,因为编译器将不会对模板执行正确的两阶段名称查找。

在sstream的第270行中,您将找到:

            …
            constexpr auto _Both = ios_base::in | ios_base::out;
            …

作为std::basic_stringbuf::seekoff()定义的一部分,该定义是一个虚拟成员函数。 std::basic_stringstream<char>包含一个成员,该成员是一个std::basic_stringbuf实例,其构造需要定义虚拟成员函数。

在包含<sstream>之后,您将定义通用operator |重载并将其引入全局命名空间。上面|表达式中的操作数仅包含非相关名称。因此,此表达式实际上不受operator |的存在的影响,因为要决定使用哪个运算符函数应该在std::basic_stringbuf::seekoff()的定义中首次遇到该表达式的地方进行。但是,据我所知,Visual C ++编译器实际上只是将模板函数实例放在翻译单元的末尾。基于[temp.point]/8,这本身是允许的。但是,Visual C ++过去也将所有名称查找延迟到模板实例化时间documented non-standard behavior上。没有/permissive-开关,编译器仍将执行此非标准名称查找作为兼容性功能。然后它将发现并尝试使用您的operator |,它比内置运算符更匹配,因为这两个操作数都是枚举类型,并且需要integral promotion。使用/permissive-,编译器将执行正确的两阶段名称查找,并正确地决定使用内置的|运算符。

/permissive-有效时,有一个/Zc:twoPhase-标志可显式打开此非标准行为。因此,您只需打开/permissive-/Zc:twoPhase-并观察到这会像预期的那样带回错误,就可以验证问题实际上是由非标准名称查找引起的。

除此之外,请注意,您的operator |不会返回任何值,因此,如果最终在任何地方实际使用此运算符,都会导致调用未定义的行为…;)