Skip to content

Commit

Permalink
ENH: Add itk::bit_cast<TDestination>(source) function
Browse files Browse the repository at this point in the history
Added a rudimentary `bit_cast` implementation for C++14/C++17, mimicking
C++20 `std::bit_cast`.
  • Loading branch information
N-Dekker authored and dzenanz committed Apr 16, 2022
1 parent 4ff05c0 commit 71e4c83
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
60 changes: 60 additions & 0 deletions Modules/Core/Common/include/itkBitCast.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*=========================================================================
*
* Copyright NumFOCUS
*
* Licensed 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.txt
*
* 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 itkBitCast_h
#define itkBitCast_h

#if __cplusplus < 202002L

# include <cstring> // For memcpy.
# include <type_traits> // For is_trivially_copyable and remove_const_t.

namespace itk
{

/** Rudimentary `bit_cast` implementation for C++14/C++17. From C++20, `std::bit_cast` is preferred.
*/
template <typename TDestination, class TSource>
TDestination
bit_cast(const TSource & source)
{
static_assert(sizeof(TDestination) == sizeof(TSource),
"The destination type should have the same size as the source type.");
static_assert(std::is_trivially_copyable<TDestination>::value, "The destination type should be trivially copyable");
static_assert(std::is_trivially_copyable<TSource>::value, "The source type should be trivially copyable.");

std::remove_const_t<TDestination> result;
std::memcpy(&result, &source, sizeof(TSource));
return result;
}

} // namespace itk

#else

// From C++20, std::bit_cast is included with the C++ Standard Library.
# include <bit>

namespace itk
{
using ::std::bit_cast;
}

#endif

#endif // itkBitCast_h
1 change: 1 addition & 0 deletions Modules/Core/Common/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,7 @@ endif()

set(ITKCommonGTests
itkAggregateTypesGTest.cxx
itkBitCastGTest.cxx
itkBooleanStdVectorGTest.cxx
itkBuildInformationGTest.cxx
itkConnectedImageNeighborhoodShapeGTest.cxx
Expand Down
46 changes: 46 additions & 0 deletions Modules/Core/Common/test/itkBitCastGTest.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*=========================================================================
*
* Copyright NumFOCUS
*
* Licensed 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.txt
*
* 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.
*
*=========================================================================*/

// First include the header file to be tested:
#include "itkBitCast.h"
#include <gtest/gtest.h>
#include <cstring> // For memcmp.

namespace
{
template <typename TDestination, class TSource>
void
Expect_return_value_is_bitwise_equal_to_function_argument(const TSource & source)
{
const auto result = itk::bit_cast<TDestination>(source);
EXPECT_EQ(std::memcmp(&result, &source, sizeof(TSource)), 0);
}
} // namespace


TEST(BitCast, ResultIsBitwiseEqualToArgument)
{
for (const int i : { -1, 0, 1 })
{
Expect_return_value_is_bitwise_equal_to_function_argument<unsigned int>(i);
}

int value;
(void)value;
Expect_return_value_is_bitwise_equal_to_function_argument<intptr_t>(&value);
}

0 comments on commit 71e4c83

Please sign in to comment.