Предупреждения или ошибки для неявного преобразования примитивов в C ++ - PullRequest
18 голосов
/ 18 декабря 2010

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

Пример

struct A *a();

bool b() {
    return a();
}

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

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

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

Примечание

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

Ответы [ 6 ]

4 голосов
/ 29 января 2014

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

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

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

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

РЕДАКТИРОВАНИЕ: добавлено примечание C ++ 11:

В Язык программирования C ++, 4-е издание , приложение к 3-му изданию было сообщено и расширено как раздел 10.5, «Неявное преобразование типов».

Исходя из прежних соображений, C ++ 11 более точно определяет «сужающие преобразования» и добавляет нотацию {} -initializer (6.3.5), с помощью которой усечения приводят к ошибке компиляции.

2 голосов
/ 19 декабря 2010

Microsoft Visual C ++ выдаст предупреждение о сужающемся преобразовании из 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)
2 голосов
/ 18 декабря 2010

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

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

1 голос
/ 19 декабря 2010

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

1 голос
/ 18 декабря 2010

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

Вы уверены, что такой подход, как 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;
}
0 голосов
/ 14 июня 2015

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

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