mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
tests and changes for final_act
This commit is contained in:
parent
652d886963
commit
b8af699165
100
include/gsl.h
100
include/gsl.h
@ -40,25 +40,97 @@ using std::shared_ptr;
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Final_act allows you to ensure something gets run at the end of a scope
|
// Final_act allows you to ensure something gets run at the end of a scope
|
||||||
template <class F>
|
template <typename F_t>
|
||||||
class Final_act
|
class Final_act_noexcept
|
||||||
{
|
{
|
||||||
public:
|
F_t f;
|
||||||
explicit Final_act(F f) : f_(f) {}
|
bool run;
|
||||||
|
|
||||||
Final_act(const Final_act&& other) : f_(other.f_) {}
|
|
||||||
Final_act(const Final_act&) = delete;
|
|
||||||
Final_act& operator=(const Final_act&) = delete;
|
|
||||||
|
|
||||||
~Final_act() { f_(); }
|
|
||||||
|
|
||||||
private:
|
public:
|
||||||
F f_;
|
explicit Final_act_noexcept(F_t f_) : f(f_), run(true) { }
|
||||||
|
|
||||||
|
~Final_act_noexcept()
|
||||||
|
{
|
||||||
|
if (!run) return;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
|
||||||
|
Final_act_noexcept(const Final_act_noexcept& s) = delete;
|
||||||
|
Final_act_noexcept(Final_act_noexcept&& s)
|
||||||
|
: f(std::move(s.f)), run(s.run)
|
||||||
|
{ s.run = false; }
|
||||||
|
|
||||||
|
Final_act_noexcept& operator=(const Final_act_noexcept& s) = delete;
|
||||||
|
|
||||||
|
Final_act_noexcept& operator=(Final_act_noexcept&& s)
|
||||||
|
{
|
||||||
|
f = std::move(s.f);
|
||||||
|
run = s.run;
|
||||||
|
s.run = false;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release() { run = false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Final_act allows you to ensure something gets run at the end of a scope
|
||||||
|
template <typename F_t>
|
||||||
|
class Final_act
|
||||||
|
{
|
||||||
|
F_t f;
|
||||||
|
bool run;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Final_act(F_t f_) : f(f_), run(true) { }
|
||||||
|
|
||||||
|
~Final_act()
|
||||||
|
{
|
||||||
|
if (!run)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try { f(); }
|
||||||
|
catch (...) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
Final_act(const Final_act& s) = delete;
|
||||||
|
|
||||||
|
Final_act(Final_act&& s) : f(std::move(s.f)), run(s.run)
|
||||||
|
{
|
||||||
|
s.run = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Final_act& operator=(const Final_act& s) = delete;
|
||||||
|
|
||||||
|
Final_act& operator=(Final_act&& s)
|
||||||
|
{
|
||||||
|
f = std::move(s.f);
|
||||||
|
run = s.run;
|
||||||
|
s.run = false;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release() { run = false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <bool b, typename T, typename U>
|
||||||
|
struct if_type_else_type { };
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
struct if_type_else_type<true, T, U> { typedef T type; };
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
struct if_type_else_type<false, T, U> { typedef U type; };
|
||||||
|
|
||||||
|
template <bool b, typename T, typename U>
|
||||||
|
using if_type_else_type_t = typename if_type_else_type<b, T, U>::type;
|
||||||
|
|
||||||
// finally() - convenience function to generate a Final_act
|
// finally() - convenience function to generate a Final_act
|
||||||
template <class F>
|
template <typename F_t, typename Final_act_t = if_type_else_type_t<
|
||||||
Final_act<F> finally(F f) { return Final_act<F>(f); }
|
noexcept(std::declval<F_t&>()()),
|
||||||
|
Final_act_noexcept<F_t>, Final_act<F_t>>>
|
||||||
|
auto finally(F_t f) {
|
||||||
|
return Final_act_t(std::move(f));
|
||||||
|
}
|
||||||
|
|
||||||
// narrow_cast(): a searchable way to do narrowing casts of values
|
// narrow_cast(): a searchable way to do narrowing casts of values
|
||||||
template<class T, class U>
|
template<class T, class U>
|
||||||
|
@ -87,6 +87,20 @@ add_test(
|
|||||||
COMMAND bounds_tests
|
COMMAND bounds_tests
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_executable(final_act_tests
|
||||||
|
final_act_tests.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(final_act_tests
|
||||||
|
UnitTest++
|
||||||
|
)
|
||||||
|
install(TARGETS final_act_tests
|
||||||
|
RUNTIME DESTINATION bin
|
||||||
|
)
|
||||||
|
add_test(
|
||||||
|
NAME final_act_tests
|
||||||
|
COMMAND final_act_tests
|
||||||
|
)
|
||||||
|
|
||||||
add_executable(maybenull_tests
|
add_executable(maybenull_tests
|
||||||
maybenull_tests.cpp
|
maybenull_tests.cpp
|
||||||
)
|
)
|
||||||
|
70
tests/final_act_tests.cpp
Normal file
70
tests/final_act_tests.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||||
|
//
|
||||||
|
// This code is licensed under the MIT License (MIT).
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <UnitTest++/UnitTest++.h>
|
||||||
|
#include <gsl.h>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Guide;
|
||||||
|
|
||||||
|
struct Increment {
|
||||||
|
int* i_;
|
||||||
|
|
||||||
|
Increment(int& i) : i_(&i) {}
|
||||||
|
|
||||||
|
void operator()() const noexcept { ++*i_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ThrowOnInvocation {
|
||||||
|
class Exception : public exception {};
|
||||||
|
void operator()() const { throw Exception(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
SUITE(finallyTests) {
|
||||||
|
TEST(SingleInvocationOnConvenienceConstruction) {
|
||||||
|
int i = 0;
|
||||||
|
{ auto f = finally(Increment(i)); }
|
||||||
|
CHECK(i == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SingleInvocationOnMoveConstruction) {
|
||||||
|
int i = 0;
|
||||||
|
{
|
||||||
|
auto f = Final_act<Increment>(Increment(i));
|
||||||
|
auto ff(move(f));
|
||||||
|
}
|
||||||
|
CHECK(i == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NoexceptFinalActIsCreated) {
|
||||||
|
int i = 0;
|
||||||
|
auto f = finally(Increment(i));
|
||||||
|
CHECK((is_same<decltype(f), Final_act_noexcept<Increment>>::value));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FinalActDoesNotThrow) {
|
||||||
|
bool exceptionCaught = false;
|
||||||
|
try {
|
||||||
|
finally(ThrowOnInvocation());
|
||||||
|
} catch (...) {
|
||||||
|
exceptionCaught = true;
|
||||||
|
}
|
||||||
|
CHECK(!exceptionCaught);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, const char* []) { return UnitTest::RunAllTests(); }
|
Loading…
Reference in New Issue
Block a user