forked from Alepha/Alepha
Invariant gadget.
This commit is contained in:
@ -39,6 +39,7 @@ add_subdirectory( Exception.test )
|
|||||||
add_subdirectory( word_wrap.test )
|
add_subdirectory( word_wrap.test )
|
||||||
add_subdirectory( string_algorithms.test )
|
add_subdirectory( string_algorithms.test )
|
||||||
add_subdirectory( template_for.test )
|
add_subdirectory( template_for.test )
|
||||||
|
add_subdirectory( Invariant.test )
|
||||||
add_subdirectory( tuplize_args.test )
|
add_subdirectory( tuplize_args.test )
|
||||||
add_subdirectory( Thread.test )
|
add_subdirectory( Thread.test )
|
||||||
add_subdirectory( assertion.test )
|
add_subdirectory( assertion.test )
|
||||||
|
44
Invariant.h
Normal file
44
Invariant.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
static_assert( __cplusplus > 2023'00 );
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Alepha/Alepha.h>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace Alepha::Hydrogen ::detail:: Invariant_m
|
||||||
|
{
|
||||||
|
inline namespace exports
|
||||||
|
{
|
||||||
|
template< typename T >
|
||||||
|
class Invariant
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const T *this_;
|
||||||
|
|
||||||
|
void
|
||||||
|
check() const
|
||||||
|
{
|
||||||
|
assert( this_->invariant() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
~Invariant()
|
||||||
|
{
|
||||||
|
check();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit
|
||||||
|
Invariant( const T *const this_ )
|
||||||
|
: this_( this_ )
|
||||||
|
{
|
||||||
|
check();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Alepha::Hydrogen::inline exports::inline Invariant_m
|
||||||
|
{
|
||||||
|
using namespace detail::Invariant_m::exports;
|
||||||
|
}
|
64
Invariant.test/0.cc
Normal file
64
Invariant.test/0.cc
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
static_assert( __cplusplus > 2023'00 );
|
||||||
|
|
||||||
|
#include "../Invariant.h"
|
||||||
|
|
||||||
|
#include <Alepha/Testing/TableTest.h>
|
||||||
|
#include <Alepha/Testing/test.h>
|
||||||
|
|
||||||
|
static auto init= Alepha::Utility::enroll <=[]
|
||||||
|
{
|
||||||
|
using namespace Alepha::Testing::exports;
|
||||||
|
|
||||||
|
"Invariant basic test"_test <=[]
|
||||||
|
{
|
||||||
|
struct ItIsFine {};
|
||||||
|
|
||||||
|
struct FakeVector
|
||||||
|
{
|
||||||
|
int size= 0;
|
||||||
|
int capacity= 0;
|
||||||
|
int *data= nullptr;
|
||||||
|
|
||||||
|
bool
|
||||||
|
invariant() const
|
||||||
|
{
|
||||||
|
return true
|
||||||
|
and ( capacity >= size )
|
||||||
|
and ( capacity < 10 )
|
||||||
|
and ( capacity == 0 or data != nullptr )
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
push_back( const int x )
|
||||||
|
{
|
||||||
|
Alepha::Invariant inv{ this };
|
||||||
|
|
||||||
|
if( size == capacity )
|
||||||
|
{
|
||||||
|
// Not fully exception safe, but just
|
||||||
|
// ignore that...
|
||||||
|
const int newCapacity= capacity * 2 + 1;
|
||||||
|
int *const data2= new int [ newCapacity ];
|
||||||
|
if( capacity > 8 ) throw ItIsFine{};
|
||||||
|
|
||||||
|
std::copy( data, data + size, data2 );
|
||||||
|
capacity= newCapacity;
|
||||||
|
delete [] data;
|
||||||
|
data= data2;
|
||||||
|
}
|
||||||
|
assert( size < capacity );
|
||||||
|
data[ size++ ]= x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FakeVector v;
|
||||||
|
|
||||||
|
for( int i= 0; i < 4; ++i ) try
|
||||||
|
{
|
||||||
|
v.push_back( i );
|
||||||
|
}
|
||||||
|
catch( const ItIsFine & ) {} // It's fine!
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
1
Invariant.test/CMakeLists.txt
Normal file
1
Invariant.test/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
unit_test( 0 )
|
Reference in New Issue
Block a user