Question

I have a function that looks like this:

template<typename T>
void some_function(T* buffer) {
    BOOST_STATIC_ASSERT(sizeof(T) <= sizeof(unsigned int));

    unsigned int temporary_buffer;
    int result = some_c_api(&temporary_buffer);
    if(result == error)
        throw some_exception();

    // originally *buffer = reinterpret_cast<T&>(temporary_buffer), but this breaks 
    // strict aliasing
    std::copy( reinterpret_cast<char*>(&temporary_buffer), 
               reinterpret_cast<char*>(&temporary_buffer) + sizeof(T),
               reinterpret_cast<char*>(buffer));
}

Is it safe to cast both unrelated buffers to char* here and copy the number of bytes the target buffer can hold? I am using a non-C++11 compiler (gcc 4.1.2).

I came upon this while refactoring some code. The original code did not have this warning because it was passing around buffers as void*. Am I correct in assuming that this was illegal?

Was it helpful?

Solution

This piece of code looks like disaster waiting to happen. If it has to exist for some reason, it should be stuffed with static assertions and comments to make the intent clear.

Basically, it will work only if these conditions hold:

  • sizeof(T) <= sizeof(unsigned int) (because you're copying from an unsigned int into a T). I see this is alreay asserted, fine.

  • T is trivially copyable (as per the C++11 std::is_trivially_copyable trait). If your compiler doesn't support the Boost equivalent of this trait, just document the requirement.

As long as these are met, it's fine. That's what trivially copyable actually means - it can be copied byte for byte. I'd just use unsigned char instead of char to stress the fact that it's bytes, not characters.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top