Предупреждения или ошибки для С++ неявного преобразования примитивов
Я немного переработал код С++ и обнаружил многочисленные ошибки, возникающие из неявных преобразований, о которых я не знаю.
Пример
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 также представляет интерес, однако эта проблема относится к базе кода С++.
Ответы
Ответ 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