Поделиться через


Предупреждение компилятора (уровень 4) C4866

Компилятор file(line_number)" может не применять порядок оценки слева направо для вызова operator_name

Замечания

Начиная с C++17 операнды операторов ->*, [], >>и << должны оцениваться в левом порядке направо. Есть два случая, в которых компилятор не может обеспечить этот порядок:

  • если одно из выражений операндов является объектом, передаваемым по значению, или содержит объект, передаваемый по значению;

  • при компиляции с использованием /clr, когда один из операндов является полем объекта или элемента массива.

Компилятор выдает предупреждение C4866, когда он не может обеспечить вычисление слева направо. Это предупреждение создается только в том случае, если /std:c++17 указано или более поздней версии, так как требование слева направо этих операторов было введено в C++17.

Это предупреждение отключено по умолчанию; Вы можете использовать /Wall или /wN 4866, чтобы включить его в командной строке в качестве предупреждения уровняN или использовать предупреждение #pragma в исходном файле. Дополнительные сведения см. в разделе "Предупреждения компилятора", отключенные по умолчанию.

Это предупреждение было введено в Visual Studio 2017 версии 15.9 в результате соответствия компилятора стандарту C++17. Код, скомпилированный без предупреждений в версиях компилятора до Visual Studio 2017 версии 15.9, теперь может создать C4866. Сведения об отключении предупреждений, представленных в определенной версии компилятора или более поздней версии, см. в разделе "Предупреждения компилятора" по версии компилятора.

Чтобы устранить это предупреждение, сначала рассмотрите необходимость оценки элементов оператора слева направо, например при оценке элементов, зависящих от порядка, побочных эффектов. Во многих случаях порядок оценки элементов не имеет наблюдаемого эффекта.

Если порядок оценки должен быть слева направо, рассмотрите возможность передачи элементов по const ссылке. Это изменение устраняет предупреждение в следующем примере кода.

Пример

В этом примере создается C4866 и показано, как исправить его:

// C4866.cpp
// compile with: /w14866 /std:c++17

class HasCopyConstructor
{
public:
    int x;

    HasCopyConstructor(int x) : x(x) {}
    HasCopyConstructor(const HasCopyConstructor& h) : x(h.x) { }
};

int operator->*(HasCopyConstructor a, HasCopyConstructor b) { return a.x + b.x; }

// This version of operator->* does not trigger the warning:
// int operator->*(const HasCopyConstructor& a, const HasCopyConstructor& b) { return a.x + b.x; }

int main()
{
    HasCopyConstructor a{ 1 };
    HasCopyConstructor b{ 2 };

    a->*b;        // C4866 for call to operator->*
};