Как программно получить все флаги компилятора, установленные / permissve- в VS2017 Update8.2 - PullRequest
0 голосов
/ 27 ноября 2018

Как получить программно, опции, включенные флагом компилятора Visual Studio 2017 / permissive-

В соответствии с документацией Microsoft / permissive- flag устанавливает параметры компилятора / Zc для строгого соответствия

Теперьприведенный ниже код компилируется в Visual Studio 2017 Update8.2 с включенным флагом только / permissive- compiler и завершается ошибкой, когда / permissive- flag не включен (в 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 голосов
/ 27 ноября 2018

Проблема возникает без /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 ++ также задерживал весь поиск имен до времени создания шаблона, которое является документированным нестандартным поведением .Без ключа /permissive- компилятор все равно будет выполнять этот нестандартный поиск имен в качестве функции совместимости.Затем он найдет и попытается использовать ваш operator |, который лучше соответствует встроенному оператору, поскольку оба операнда имеют тип перечисления и потребуют интегральное повышение /permissive- компилятор выполнит правильный двухфазный поиск имени и правильно решит использовать вместо этого встроенный оператор |.

Существует флаг /Zc:twoPhase- дляявно включите это нестандартное поведение, когда действует /permissive-.Таким образом, вы можете проверить, что проблема на самом деле вызвана нестандартным поиском имени, просто включив /permissive- и /Zc:twoPhase- и заметив, что это возвращает ошибку, как и следовало ожидать ...

Кроме этого, обратите внимание, что ваш operator | не возвращает значение, поэтому, если вы в конечном итоге фактически используете эту функцию оператора, вы в конечном итоге вызовете неопределенное поведение…;)

...