make std :: необязательный конструктор выдает неявные предупреждения о преобразовании

#c #compiler-warnings #implicit-conversion #clang

#c #компилятор-предупреждения #неявное преобразование #clang

Вопрос:

Я пытаюсь избавить свою кодовую базу от неявных преобразований с потерями, поэтому я компилирую с -Wconversion флагом в clang . Ожидается, что следующий код выдаст предупреждение, но этого не происходит.

 #include <cstddef>
#include <iostream>
#include <limits>
#include <optional>


int main() {
  size_t x = std::numeric_limits<size_t>::max();
  std::cout << x << std::endl;

  auto x2 = std::make_optional<uint8_t>(x);
  std::cout << (int)*x2 << std::endl;

  return 0;
}
  

В make_optional строке my size_t автоматически сужается до a uint8_t . Если вместо этого я напишу uint8_t x2 = x; , например, я получу ожидаемое предупреждение о сужении преобразования.

Это также происходит, когда я использую std::optional конструктор. В приведенном мной коде вызывается make_optional overload 2, который вызывает необязательную перегрузку конструктора 6 . Это создает необязательное значение, как при прямой инициализации содержащегося значения, а прямая инициализация не вызывает неявного предупреждения о сужении преобразования.

optional Есть ли какой-либо способ заставить приведенный выше код вызвать предупреждение о сужении преобразования, кроме написания собственного класса, который не скрывает сужающие преобразования?

Комментарии:

1. Я собирался сказать «использовать clang-tidy», но, видимо, для этого нет проверки. Даже в сборке с сегодняшнего master, 9.0.0svn. Возможно, другой статический анализатор может обнаружить такой случай.

2. make_optional считается, что используется дедукция… остальное используется напрямую optional<T> .

3. Возможно, запишите его в libstdc , я не совсем уверен, почему это не генерирует предупреждение, как это сделал сам создатель аналогичного конструктора. Интересно, что я также получил предупреждение во всех случаях с MSVC (C4244 или C4267 для size_t).

4. Нет компилятора под рукой, но не optional<uint8_t>{x} выходит из строя по желанию?

Ответ №1:

Инициализация списка запрещает сужение преобразований.

Кстати, похоже, что некоторые компиляторы предупреждают об этой проблеме: https://godbolt.org/z/P8Mv8v83d