Added call_if_valid()

This commit is contained in:
Davis King 2020-09-05 14:38:24 -04:00
parent e7ec6b7777
commit 7dcc7b4ebc
2 changed files with 77 additions and 0 deletions

View File

@ -3,6 +3,7 @@
#ifndef DLIB_METApROGRAMMING_Hh_ #ifndef DLIB_METApROGRAMMING_Hh_
#define DLIB_METApROGRAMMING_Hh_ #define DLIB_METApROGRAMMING_Hh_
#include "algs.h"
namespace dlib namespace dlib
{ {
@ -62,6 +63,45 @@ namespace dlib
// base case // base case
template <> struct make_compile_time_integer_range<0> { typedef compile_time_integer_list<> type; }; template <> struct make_compile_time_integer_range<0> { typedef compile_time_integer_list<> type; };
// ----------------------------------------------------------------------------------------
namespace impl
{
template <
typename Funct,
typename... Args,
typename int_<decltype(std::declval<Funct>()(std::declval<Args>()...))>::type = 0
>
bool call_if_valid (
special_,
Funct&& f, Args&&... args
)
{
f(std::forward<Args>(args)...);
return true;
}
template <
typename Funct,
typename... Args
>
bool call_if_valid (
general_,
Funct&& /*f*/, Args&&... /*args*/
) { return false; }
}
template <typename Funct, typename... Args>
bool call_if_valid(Funct&& f, Args&&... args)
/*!
ensures
- if f(std::forward<Args>(args)...) is a valid expression then we evaluate it and return
true. Otherwise we do nothing and return false.
!*/
{
return impl::call_if_valid(special_(), f, std::forward<Args>(args)...);
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
} }

View File

@ -7,6 +7,7 @@
#include <cstdlib> #include <cstdlib>
#include <ctime> #include <ctime>
#include <dlib/algs.h> #include <dlib/algs.h>
#include <dlib/metaprogramming.h>
#include "tester.h" #include "tester.h"
@ -70,6 +71,41 @@ namespace
} }
void test_call_if_valid()
{
int value = 0;
auto foo = [&](int a, int b) { value += a + b; };
auto bar = [&](std::string) { value++; };
auto baz = [&]() { value++; };
DLIB_TEST(value == 0);
DLIB_TEST(call_if_valid(baz));
DLIB_TEST(value == 1);
DLIB_TEST(!call_if_valid(foo));
DLIB_TEST(value == 1);
DLIB_TEST(!call_if_valid(bar));
DLIB_TEST(value == 1);
DLIB_TEST(call_if_valid(bar, "stuff"));
DLIB_TEST(value == 2);
DLIB_TEST(!call_if_valid(baz, "stuff"));
DLIB_TEST(value == 2);
DLIB_TEST(call_if_valid(foo, 3, 1));
DLIB_TEST(value == 6);
DLIB_TEST(!call_if_valid(bar, 3, 1));
DLIB_TEST(value == 6);
// make sure stateful lambdas are modified when called
value = 0;
auto stateful = [&value, i = value]() mutable { ++i; value = i; };
DLIB_TEST(call_if_valid(stateful));
DLIB_TEST(value == 1);
DLIB_TEST(call_if_valid(stateful));
DLIB_TEST(value == 2);
DLIB_TEST(call_if_valid(stateful));
DLIB_TEST(value == 3);
}
class metaprogramming_tester : public tester class metaprogramming_tester : public tester
@ -85,6 +121,7 @@ namespace
) )
{ {
metaprogramming_test(); metaprogramming_test();
test_call_if_valid();
} }
} a; } a;