BOOST_STATIC_WARNING - PullRequest
       12

BOOST_STATIC_WARNING

4 голосов
/ 25 мая 2011

У меня недавно были некоторые проблемы с неявным приведением 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. Мой буст 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 TSource& 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 TIntegralContant&)
    {
        static_cast<void>(1 / TIntegralContant::value);
    }
}

#define MY_STATIC_WARNING(value_) \
    ::detail::test_warning(::boost::integral_constant<bool, value_ >())

1 Ответ

1 голос
/ 26 мая 2011

Какую версию 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), вы 'хорошо бы пойти скрещивает пальцы

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