1
0
forked from Alepha/Alepha

Add a unique pointer dynamic cast utility.

This commit is contained in:
2024-03-31 10:33:03 -04:00
parent e901aaedda
commit 53a4d91a23
4 changed files with 101 additions and 0 deletions

View File

@ -2,3 +2,4 @@ target_sources( alepha PRIVATE
fancyTypeName.cc
)
add_subdirectory( derived_pointer_cast.test )

View File

@ -0,0 +1,41 @@
static_assert( __cplusplus > 2020'99 );
#pragma once
#include <Alepha/Alepha.h>
#include <memory>
namespace Alepha::Hydrogen::Utility ::detail:: derived_pointer_cast_m
{
inline namespace exports
{
template< typename Target, typename Source >
std::unique_ptr< Target > derived_pointer_cast( std::unique_ptr< Source > source );
}
template< typename Target, typename Source >
std::unique_ptr< Target >
exports::derived_pointer_cast( std::unique_ptr< Source > source )
{
if( Target *const conv= dynamic_cast< Target * >( source.get() ); not conv )
{
// TODO: More precise Alepha exception here.
throw std::bad_cast{};
}
else
{
// It's safe to release here, because we're taking ownership below.
source.release();
// We reuse the conversion pointer so we can avoid a double-trip thru the
// RTTI pathway.
return std::unique_ptr< Target >{ conv };
}
}
}
namespace Alepha::Hydrogen::Utility::inline exports::inline derived_pointer_cast_m
{
using namespace detail::derived_pointer_cast_m::exports;
}

View File

@ -0,0 +1,58 @@
static_assert( __cplusplus > 2020'99 );
#include "../derived_pointer_cast.h"
#include <Alepha/Testing/TableTest.h>
#include <Alepha/Testing/test.h>
#include <Alepha/Utility/evaluation_helpers.h>
static auto init= Alepha::Utility::enroll <=[]
{
using namespace Alepha::Testing::exports;
struct Base
{
virtual ~Base()= default;
};
struct Derived : Base {};
struct Derived2 : Base {};
"Can `derived_pointer_cast` work on simple cases?"_test <=TableTest
<
[]( std::function< std::unique_ptr< Base >() > makeBase )
{
auto base= makeBase();
return static_cast< bool >( Alepha::Utility::derived_pointer_cast< Derived >( std::move( base ) ) );
}
>
::Cases
{
{ "Is derived", { [] { return std::make_unique< Derived >(); } }, true },
{ "Not derived", { [] { return std::make_unique< Base >(); } }, std::type_identity< std::bad_cast >{} },
{ "Other derived", { [] { return std::make_unique< Derived2 >(); } }, std::type_identity< std::bad_cast >{} },
};
struct Alien
{
virtual ~Alien()= default;
};
struct AlienDerived : Alien {};
"Alien Test"_test <=TableTest
<
[]( std::function< std::unique_ptr< Alien >() > makeBase )
{
auto base= makeBase();
return static_cast< bool >( Alepha::Utility::derived_pointer_cast< Derived >( std::move( base ) ) );
}
>
::Cases
{
{ "Alien", { [] { return std::make_unique< Alien >(); } }, std::type_identity< std::bad_cast >{} },
{ "Alien Derived", { [] { return std::make_unique< AlienDerived >(); } }, std::type_identity< std::bad_cast >{} },
};
};

View File

@ -0,0 +1 @@
unit_test( 0 )