#c #boost #compiler-warnings
#c #повышение #предупреждения компилятора
Вопрос:
Недавно у меня возникли некоторые проблемы с неявным приведением C , поэтому я ищу способ предупредить людей, если кто-то попытается присвоить int32_t uint64_t или что-то еще. BOOST_STATIC_ASSERT
это сотворило бы чудеса для этого, за исключением того, что кодовая база, с которой я работаю, довольно большая и опирается на множество неявных приведений, поэтому немедленное нарушение всего с помощью утверждений нереально.
Похоже, что BOOST_STATIC_WARNING было бы идеально для меня, однако я не могу заставить его фактически выдавать предупреждение. Что-то вроде этого ничего не даст:
typedef boost::is_same<int64_t, int32_t> same_type;
BOOST_STATIC_WARNING(same_type::value);
Моим компилятором является g 4.4.3 с —std=c 0x -Wall -Wextra. Мой Boost равен 1.46.1.
Проблема, которую я пытаюсь решить здесь, заключается в том, что у нас есть тип буфера, который имеет такие методы, как uint8_t GetUInt8(size_type index)
, void SetUInt32(size_type index, uint32_t value)
и т.д. Итак, вы видите использование следующим образом:
x = buffer.GetUInt16(96);
Проблема в том, что нет гарантии, что при чтении 16-разрядного целого числа без знака это x
на самом деле 16 бит. Хотя человек, который изначально написал эту строку, сделал это правильно (надеюсь), если тип x
изменится, эта строка будет автоматически прерываться.
Мое решение состоит в том, чтобы создать safe_convertable<T>
тип, подобный этому:
template <typename T>
struct safe_convertable
{
public:
template <typename TSource>
safe_convertable(const TSourceamp; val)
{
typedef boost::is_same<T, TSource> same_type;
BOOST_STATIC_WARNING(same_type::value);
_val = val;
}
template <typename TDestination>
operator TDestination ()
{
typedef boost::is_same<T, TDestination> same_type;
BOOST_STATIC_WARNING(same_type::value);
return _val;
}
private:
T _val;
};
и измените методы, чтобы возвращать и принимать эти безопасные ссылки: safe_reference<uint8_t> GetUInt8(size_type index)
, void SetUInt32(size_type index, safe_reference<uint32_t> value)
(это сокращенная версия, есть другие операторы и еще много чего, что вы можете сделать со ссылками).
В любом случае, это отлично работает с BOOST_STATIC_ASSERT
, за исключением того факта, что мне нужны предупреждения, а не ошибки.
Для любопытных, я сам реализовал функцию предупреждения, которая работает нормально, но я бы предпочел вариант Boost, чтобы получить все остальные функции Boost (это работает только внутри функции).
namespace detail
{
template <typename TIntegralContant>
inline void test_warning(const TIntegralContantamp;)
{
static_cast<void>(1 / TIntegralContant::value);
}
}
#define MY_STATIC_WARNING(value_)
::detail::test_warning(::boost::integral_constant<bool, value_ >())
Комментарии:
1. «Я не могу заставить его на самом деле выдавать предупреждение. Что-то вроде этого ничего не даст:»
2. @Nawaz: Он написал «Я не могу заставить его на самом деле выдавать предупреждение».
3. @Travis: Он выдает предупреждение с помощью
g 4.3.4
: ideone.com/68yOM … поскольку в ideone нет boost дляc 0x
, поэтому я не могу скомпилировать его с--std=c 0x
опцией.4. Зачем вам предупреждение, если вы не собираетесь устранять проблему? Это просто добавило шума.
5. @Bo: Я исправлю проблему, я просто не хочу прерывать сборки в то же время. Это проблемы, которые необходимо исправить, просто не немедленно .
Ответ №1:
Какую версию Boost вы используете? Этот комментарий может быть причиной того, что ваше собственное предупреждение работает, но версия boost этого не делает:
// 6. replaced implementation with one which depends solely on
// mpl::print<>. The previous one was found to fail for functions
// under recent versions of gcc and intel compilers - Robert Ramey
Я предполагаю, что если бы вы обновились до последней версии Boost (например, 1.46.1), все было бы в порядке. скрещивает пальцы
Комментарии:
1. Ого! Вот и вся эта идея. Не возражаете против регистрации ошибки?