65 lines
2.1 KiB
C
65 lines
2.1 KiB
C
|
/*
|
||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||
|
* or more contributor license agreements. See the NOTICE file
|
||
|
* distributed with this work for additional information
|
||
|
* regarding copyright ownership. The ASF licenses this file
|
||
|
* to you under the Apache License, Version 2.0 (the
|
||
|
* "License"); you may not use this file except in compliance
|
||
|
* with the License. You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing,
|
||
|
* software distributed under the License is distributed on an
|
||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||
|
* KIND, either express or implied. See the License for the
|
||
|
* specific language governing permissions and limitations
|
||
|
* under the License.
|
||
|
*/
|
||
|
|
||
|
#ifndef THRIFT_UTIL_BITWISECAST_H_
|
||
|
#define THRIFT_UTIL_BITWISECAST_H_
|
||
|
|
||
|
#include <boost/static_assert.hpp>
|
||
|
|
||
|
// Use this to get around strict aliasing rules.
|
||
|
// For example, uint64_t i = bitwise_cast<uint64_t>(returns_double());
|
||
|
// The most obvious implementation is to just cast a pointer,
|
||
|
// but that doesn't work.
|
||
|
// For a pretty in-depth explanation of the problem, see
|
||
|
// http://cellperformance.beyond3d.com/articles/2006/06/ (...)
|
||
|
// understanding-strict-aliasing.html
|
||
|
template <typename To, typename From>
|
||
|
static inline To bitwise_cast(From from) {
|
||
|
BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To));
|
||
|
|
||
|
// BAD!!! These are all broken with -O2.
|
||
|
//return *reinterpret_cast<To*>(&from); // BAD!!!
|
||
|
//return *static_cast<To*>(static_cast<void*>(&from)); // BAD!!!
|
||
|
//return *(To*)(void*)&from; // BAD!!!
|
||
|
|
||
|
// Super clean and partially blessed by section 3.9 of the standard.
|
||
|
//unsigned char c[sizeof(from)];
|
||
|
//memcpy(c, &from, sizeof(from));
|
||
|
//To to;
|
||
|
//memcpy(&to, c, sizeof(c));
|
||
|
//return to;
|
||
|
|
||
|
// Slightly more questionable.
|
||
|
// Same code emitted by GCC.
|
||
|
//To to;
|
||
|
//memcpy(&to, &from, sizeof(from));
|
||
|
//return to;
|
||
|
|
||
|
// Technically undefined, but almost universally supported,
|
||
|
// and the most efficient implementation.
|
||
|
union {
|
||
|
From f;
|
||
|
To t;
|
||
|
} u;
|
||
|
u.f = from;
|
||
|
return u.t;
|
||
|
}
|
||
|
|
||
|
#endif
|