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( string_algorithms.test )
|
||||
add_subdirectory( template_for.test )
|
||||
add_subdirectory( Invariant.test )
|
||||
add_subdirectory( tuplize_args.test )
|
||||
add_subdirectory( Thread.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