Reputation: 27633
I've recently had some trouble with C++'s implicit casting, so I'm looking for a way to warn people if somebody attempts to assign an int32_t to a uint64_t or whatever. BOOST_STATIC_ASSERT
would work wonders for this, except that the code base I'm working with is quite large and relies on a lot of implicit casting, so immediately breaking everything with assertions is unrealistic.
It looks like BOOST_STATIC_WARNING would be ideal for me, however, I cannot get it to actually emit a warning. Something like this won't do anything:
typedef boost::is_same<int64_t, int32_t> same_type;
BOOST_STATIC_WARNING(same_type::value);
My compiler is g++ 4.4.3 with --std=c++0x -Wall -Wextra. My Boost is 1.46.1.
The problem I'm trying to solve here is that we have a buffer type which has methods like uint8_t GetUInt8(size_type index)
, void SetUInt32(size_type index, uint32_t value)
, etc. So, you see usage like this:
x = buffer.GetUInt16(96);
The problem is that there is no guarantee that, while you are reading a 16-bit unsigned integer, that x
is actually 16-bits. While the person who originally wrote that line did it properly (hopefully), if the type of x
changes, this line will break silently.
My solution is to create a safe_convertable<T>
type like so:
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;
};
and change the methods to return and accept these safe references: safe_reference<uint8_t> GetUInt8(size_type index)
, void SetUInt32(size_type index, safe_reference<uint32_t> value)
(that's the short version, there are other operators and whatnot you can do to references).
Anyway, this works great with BOOST_STATIC_ASSERT
, save for the fact that I want warnings and not errors.
For the curious, I've implemented the warning thing myself, which works fine, but I'd prefer the Boost variety so that I get all the other Boost features (this only works inside a function).
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_ >())
Upvotes: 4
Views: 1101
Reputation: 10206
What version of Boost are you using? This comment may be the reason why your own warning works, but the boost version does not:
// 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
I'm guessing if you upgraded to a recent version of Boost (e.g. 1.46.1), you'd be good to go. crosses fingers
Upvotes: 1