Skip to content

Instantly share code, notes, and snippets.

@eguiraud
Last active September 24, 2017 17:10
Show Gist options
  • Select an option

  • Save eguiraud/fb79c45fadbcba03182d6bbf421fa5b8 to your computer and use it in GitHub Desktop.

Select an option

Save eguiraud/fb79c45fadbcba03182d6bbf421fa5b8 to your computer and use it in GitHub Desktop.
std::not_fn c++11 implementation
#include <type_traits> // std::decay
#include <utility> // std::forward, std::declval
namespace Internal {
template <typename F>
class not_fn_t {
typename std::decay<F>::type fFun;
public:
explicit not_fn_t(F &&f) : fFun(std::forward<F>(f)) {}
not_fn_t(not_fn_t &&h) = default;
not_fn_t(const not_fn_t &f) = default;
template <class... Args>
auto operator()(Args &&... args) & -> decltype(
!std::declval<typename std::result_of<typename std::decay<F>::type(Args...)>::type>())
{
return !fFun(std::forward<Args>(args)...);
}
template <class... Args>
auto operator()(Args &&... args) const & -> decltype(
!std::declval<typename std::result_of<typename std::decay<F>::type const(Args...)>::type>())
{
return !fFun(std::forward<Args>(args)...);
}
};
}
namespace std {
template <typename F>
Internal::not_fn_t<F> not_fn(F &&f)
{
return Internal::not_fn_t<F>(std::forward<F>(f));
}
}
#include "not_fn.cpp"
#include <cassert>
struct Boolean {
bool b;
public:
explicit Boolean(bool b) : b(b) {}
Boolean &operator!() { b = !b; return *this; }
};
int main() {
assert(std::not_fn([]() { return false; })());
int a = 1;
assert(std::not_fn([a]() { return a == 0; })());
int *p = nullptr;
assert(std::not_fn([&p]() { return p; })());
std::function<Boolean(bool)> f = [](bool b) { return Boolean(b); };
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment