forked from Alepha/Alepha
Add a unique pointer dynamic cast utility.
This commit is contained in:
@ -2,3 +2,4 @@ target_sources( alepha PRIVATE
|
|||||||
fancyTypeName.cc
|
fancyTypeName.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_subdirectory( derived_pointer_cast.test )
|
||||||
|
41
Utility/derived_pointer_cast.h
Normal file
41
Utility/derived_pointer_cast.h
Normal 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;
|
||||||
|
}
|
58
Utility/derived_pointer_cast.test/0.cc
Normal file
58
Utility/derived_pointer_cast.test/0.cc
Normal 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 >{} },
|
||||||
|
};
|
||||||
|
};
|
1
Utility/derived_pointer_cast.test/CMakeLists.txt
Normal file
1
Utility/derived_pointer_cast.test/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
unit_test( 0 )
|
Reference in New Issue
Block a user