简体   繁体   中英

How to get programatically all the compiler flags set by /permissve- in VS2017 Update8.2

How to get programatically, options enabled by Visual Studio 2017 compiler flag /permissive-

As per Microsoft Documentation /permissive- flag sets the /Zc compiler options for strict conformance

Now the below code gets compiled on Visual Studio 2017 Update8.2 with only /permissive- compiler flag on , and fails when /permissive- flag is not turned on (on 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;
}

I want to know which compiler flag of /Zc fixed this

The problem occurs without /permissive- because the compiler will not perform proper two-phase name lookup for templates.

In sstream, line 270 you'll find:

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

as part of the definition of std::basic_stringbuf::seekoff() which is a virtual member function. std::basic_stringstream<char> contains a member that is an std::basic_stringbuf instance, the construction of which requires the definition of the virtual member functions.

After including <sstream> , you define and introduce into the global namespace a generic operator | overload. The operands in the | expression above contain only non-dependent names. Therefore, this expression should actually not be affected by the presence of your operator | because the decision which operator function to use should happen at the point where the expression is first encountered in the definition of std::basic_stringbuf::seekoff() . However, (as far as my understanding goes) the Visual C++ compiler will effectively just put template function instances at the end of the translation unit. This in itself is allowed based on [temp.point]/8 . However, Visual C++ used to also delay all name lookup to template instantiation time which is documented non-standard behavior . Without the /permissive- switch, the compiler will still perform this non-standard name lookup as a compatibility feature. It will then find and try to use your operator | which is a better match than the built-in operator because both operands are of enumeration type and would require an integral promotion . With /permissive- , the compiler will perform proper two-phase name lookup and correctly decide to use the built-in | operator instead.

There is a /Zc:twoPhase- flag to explicitly turn on this non-standard behavior when /permissive- is in effect. Thus, you can verify that the problem actually is caused by non-standard name lookup simply by switching on /permissive- and /Zc:twoPhase- and observing that this brings back the error as one would expect…

Apart from that, note that your operator | does not return a value, so if you end up actually using this operator function anywhere, you'll end up invoking undefined behavior… ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM