Подтвердить что ты не робот

Предупреждения или ошибки для С++ неявного преобразования примитивов

Я немного переработал код С++ и обнаружил многочисленные ошибки, возникающие из неявных преобразований, о которых я не знаю.

Пример

struct A *a();

bool b() {
    return a();
}

void c() {
    int64_t const d(b());
}

Вопросы

  • В b возвращаемый тип a беззвучно добавляется к bool.
  • В c значение, возвращаемое с b, равномерно продвигается до int64_t.

Вопрос

Как я могу получать предупреждения или ошибки для неявного преобразования между примитивными типами?

Примечание

  • Использование -Wconversion, по-видимому, вызывает только несколько произвольных преобразований, не связанных с приведенным выше примером.
  • BOOST_STRONG_TYPEDEF не является вариантом (мои типы должны быть POD, поскольку они используются в дисковых структурах).
  • C также представляет интерес, однако эта проблема относится к базе кода С++.
4b9b3361

Ответ 1

В языке программирования С++, 3-е издание, добавлении C.6, а именно: "Неявное преобразование типов", Bjarne Stroustrup классифицирует конверсии в качестве рекламных акций и конверсии: первые "сохраняют значения" (ваш случай 2), а второй - нет (случай 1).

О конверсиях, он говорит, что "фундаментальные типы могут быть преобразованы друг в друга в пугающем числе способов. На мой взгляд, допускается слишком много преобразований". и "Компилятор может предупредить о многих сомнительных конверсиях. К счастью, многие компиляторы действительно делают".

акции с другой стороны безопасны, и похоже, что компилятор не должен давать предупреждение для них.

Предупреждения компилятора обычно не являются обязательными. Обычно в сценариях С++ и окончательных документах ANSI сообщается, что "разработчики должны выпустить предупреждение", где это предлагается: вы можете проверить его самостоятельно для получения дополнительной информации при необходимости.

EDITED: добавлено примечание С++ 11:

В Язык программирования С++, 4-е издание, добавлено 3-е издание, добавлено в раздел 10.5 "Неявное преобразование типов" " еще раз.

Будучи предыдущими соображениями, С++ 11 более точно определяет "сужение конверсий" и добавляет нотацию {} -initializer (6.3.5), с которой усечения приводят к ошибке компиляции.

Ответ 2

Если вы используете gcc, вы попробовали -Wall -Wextra в основном проверьте эту страницу
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

Если это не GCC, напишите подробности компилятора.

Ответ 3

Microsoft Visual С++ даст предупреждение о суживающем преобразовании от A* до bool.

См. предупреждение компилятора C4800

Продвижение, с другой стороны, не является "опасным" преобразованием, потому что невозможно потерять данные.

РЕДАКТИРОВАТЬ: Демонстрация

C:\Users\Ben>copy con test.cpp
bool f( void ) { return new int(); }
^Z
        1 file(s) copied.

C:\Users\Ben>cl /c /W4 test.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
test.cpp(1) : warning C4800: 'int *' : forcing value to bool 'true' or 'false' (
performance warning)

Ответ 4

Насколько я понимаю, вы не можете контролировать неявное преобразование между примитивные типы: он задан стандартом и любым совместимым компилятор просто выполнит его молча.

Вы уверены, что такой подход, как BOOST_STRONG_TYPEDEF, не будет работать в вашем проблема? Класс без виртуальных функций-членов и только один примитив элемент данных в основном не более чем тип данных POD. Ты можешь просто следуйте одному и тому же подходу и только разрешите преобразование в базу примитивный тип; Пример:

#include <iostream>
#include <stdexcept>

struct controlled_int {
  // allow creation from int
  controlled_int(int x) : value_(x) { };
  controlled_int& operator=(int x) { value_ = x; return *this; };
  // disallow assignment from bool; you might want to use BOOST_STATIC_ASSERT instead
  controlled_int& operator=(bool b) { throw std::logic_error("Invalid assignment of bool to controlled_int"); return *this; };

  // creation from bool shouldn't happen silently
  explicit controlled_int(bool b) : value_(b) { };

  // conversion to int is allowed
  operator int() { return value_; };

  // conversion to bool errors out; you might want to use BOOST_STATIC_ASSERT instead

  operator bool() { throw std::logic_error("Invalid conversion of controlled_int to bool"); };

  private:
    int value_;
};

int main()
{
  controlled_int a(42);

  // This errors out:
  // bool b = a;

  // This gives an error as well:
  //a = true;

  std::cout << "Size of controlled_int: " << sizeof(a) << std::endl;
  std::cout << "Size of int: " << sizeof(int) << std::endl;

  return 0;
}

Ответ 5

Вы можете использовать один из доступных инструментов статического анализа, такие как Clint или эквиваленты С++, или один из доступных в продаже инструментов. Многие из этих инструментов могут отображать проблемные неявные преобразования.

Ответ 6

Напишите собственный плагин clang для диагностики ваших проблем. Мы многое делаем в коде LibreOffice. Приходите искать наш источник, если хотите вдохнуть в http://cgit.freedesktop.org/libreoffice/core/tree/compilerplugins/clang