mirror of https://github.com/oxen-io/lokinet
Merge branch 'fix-big-ooooofff'
commit
223f2702d3
@ -0,0 +1 @@
|
||||
#include <util/memfn.hpp>
|
@ -0,0 +1,91 @@
|
||||
#ifndef LLARP_UTIL_MEMFN
|
||||
#define LLARP_UTIL_MEMFN
|
||||
|
||||
#include <util/memfn_traits.hpp>
|
||||
#include <util/object.hpp>
|
||||
#include <util/traits.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
template < typename Obj >
|
||||
struct MemFnDereference
|
||||
{
|
||||
// clang-format off
|
||||
static inline Obj& derefImp(Obj& obj, std::false_type)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
template < typename Type >
|
||||
static inline Obj& derefImp(Type& obj, std::true_type)
|
||||
{
|
||||
return *obj;
|
||||
}
|
||||
|
||||
template < typename Type >
|
||||
static inline Obj& derefImp(const Type& obj, std::true_type)
|
||||
{
|
||||
return *obj;
|
||||
}
|
||||
|
||||
template < typename Type >
|
||||
static inline Obj& deref(Type& obj)
|
||||
{
|
||||
return derefImp(obj, traits::is_pointy< Type >());
|
||||
}
|
||||
|
||||
template < typename Type >
|
||||
static inline Obj& deref(const Type& obj)
|
||||
{
|
||||
return derefImp(obj, traits::is_pointy< Type >());
|
||||
}
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
template < typename Prototype, typename Instance >
|
||||
class MemFn
|
||||
{
|
||||
using traits = MemFnTraits< Prototype >;
|
||||
|
||||
static_assert(traits::IsMemFn, "");
|
||||
|
||||
public:
|
||||
using result_type = typename traits::result_type;
|
||||
|
||||
private:
|
||||
Prototype m_func;
|
||||
object::Proxy< Instance > m_instance;
|
||||
|
||||
using Deref = MemFnDereference< typename traits::class_type >;
|
||||
|
||||
public:
|
||||
MemFn(Prototype prototype, const Instance& instance)
|
||||
: m_func(prototype), m_instance(instance)
|
||||
{
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
result_type
|
||||
operator()(Args&&... args) const
|
||||
{
|
||||
return (Deref::deref(m_instance.value())
|
||||
.*m_func)(std::forward< Args >(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template < typename Prototype, typename Instance >
|
||||
MemFn< Prototype, Instance >
|
||||
memFn(Prototype prototype, const Instance& instance)
|
||||
{
|
||||
return MemFn< Prototype, Instance >(prototype, instance);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1 @@
|
||||
#include <util/memfn_traits.hpp>
|
@ -0,0 +1,107 @@
|
||||
#ifndef LLARP_UTIL_MEMFN_TRAITS
|
||||
#define LLARP_UTIL_MEMFN_TRAITS
|
||||
|
||||
#include <util/object.hpp>
|
||||
#include <util/traits.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
template < typename Prototype, typename TestPrototype >
|
||||
struct MemFnTraitsImpl;
|
||||
|
||||
template < typename Prototype >
|
||||
struct MemFnTraits : public MemFnTraitsImpl< Prototype, Prototype >
|
||||
{
|
||||
};
|
||||
|
||||
template < typename Prototype, typename Return, typename Type,
|
||||
typename... Args >
|
||||
class MemFnTraitsClass
|
||||
{
|
||||
using NonCVTag = traits::Tag< 0 >;
|
||||
using ConstTag = traits::Tag< 1 >;
|
||||
using VolTag = traits::Tag< 2 >;
|
||||
using ConstVolTag = traits::Tag< 3 >;
|
||||
|
||||
// clang-format off
|
||||
static constexpr NonCVTag test(Return (Type::*)(Args...));
|
||||
static constexpr ConstTag test(Return (Type::*)(Args...) const);
|
||||
static constexpr VolTag test(Return (Type::*)(Args...) volatile);
|
||||
static constexpr ConstVolTag test(Return (Type::*)(Args...) const volatile);
|
||||
// clang-format on
|
||||
public:
|
||||
static constexpr bool IsConst =
|
||||
((sizeof((test)((Prototype)0)) - 1) & 1) != 0;
|
||||
static constexpr bool IsVolatile =
|
||||
((sizeof((test)((Prototype)0)) - 1) & 2) != 0;
|
||||
|
||||
using ctype = std::conditional_t< IsConst, const Type, Type >;
|
||||
using type = std::conditional_t< IsVolatile, volatile ctype, ctype >;
|
||||
};
|
||||
|
||||
template < typename Prototype, typename Return, typename Type,
|
||||
typename... Args >
|
||||
struct MemFnTraitsImpl< Prototype, Return (Type::*)(Args...) >
|
||||
{
|
||||
static constexpr bool IsMemFn = true;
|
||||
|
||||
using class_type =
|
||||
typename MemFnTraitsClass< Prototype, Return, Type, Args... >::type;
|
||||
|
||||
using result_type = Return;
|
||||
};
|
||||
|
||||
template < typename Prototype, typename Return, typename Type,
|
||||
typename... Args >
|
||||
struct MemFnTraitsImpl< Prototype, Return (Type::*)(Args...) const >
|
||||
{
|
||||
static constexpr bool IsMemFn = true;
|
||||
|
||||
using class_type =
|
||||
typename MemFnTraitsClass< Prototype, Return, Type, Args... >::type;
|
||||
|
||||
using result_type = Return;
|
||||
};
|
||||
|
||||
template < typename Prototype, typename Return, typename Type,
|
||||
typename... Args >
|
||||
struct MemFnTraitsImpl< Prototype, Return (Type::*)(Args...) volatile >
|
||||
{
|
||||
static constexpr bool IsMemFn = true;
|
||||
|
||||
using class_type =
|
||||
typename MemFnTraitsClass< Prototype, Return, Type, Args... >::type;
|
||||
|
||||
using result_type = Return;
|
||||
};
|
||||
|
||||
template < typename Prototype, typename Return, typename Type,
|
||||
typename... Args >
|
||||
struct MemFnTraitsImpl< Prototype,
|
||||
Return (Type::*)(Args...) const volatile >
|
||||
{
|
||||
static constexpr bool IsMemFn = true;
|
||||
|
||||
using class_type =
|
||||
typename MemFnTraitsClass< Prototype, Return, Type, Args... >::type;
|
||||
|
||||
using result_type = Return;
|
||||
};
|
||||
|
||||
template < typename Prototype, typename TestPrototype >
|
||||
struct MemFnTraitsImpl
|
||||
{
|
||||
static constexpr bool IsMemFn = false;
|
||||
|
||||
using result_type = void;
|
||||
using class_type = void;
|
||||
};
|
||||
} // namespace util
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,68 @@
|
||||
#include <util/memfn.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using namespace llarp;
|
||||
|
||||
struct Foo
|
||||
{
|
||||
bool
|
||||
empty()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
constEmpty() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
arg(int v)
|
||||
{
|
||||
return v + 1;
|
||||
}
|
||||
|
||||
int
|
||||
constArg(int v) const
|
||||
{
|
||||
return v - 1;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(MemFn, call)
|
||||
{
|
||||
Foo foo;
|
||||
ASSERT_FALSE(util::memFn(&Foo::empty, &foo)());
|
||||
ASSERT_TRUE(util::memFn(&Foo::constEmpty, &foo)());
|
||||
ASSERT_EQ(11, util::memFn(&Foo::arg, &foo)(10));
|
||||
ASSERT_EQ(9, util::memFn(&Foo::constArg, &foo)(10));
|
||||
|
||||
ASSERT_TRUE(util::memFn(&Foo::constEmpty, foo)());
|
||||
ASSERT_EQ(9, util::memFn(&Foo::constArg, foo)(10));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
class MemFnType : public ::testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
TYPED_TEST_SUITE_P(MemFnType);
|
||||
|
||||
TYPED_TEST_P(MemFnType, Smoke)
|
||||
{
|
||||
TypeParam foo;
|
||||
ASSERT_TRUE(util::memFn(&Foo::constEmpty, foo)());
|
||||
ASSERT_TRUE(util::memFn(&Foo::constEmpty, &foo)());
|
||||
}
|
||||
|
||||
REGISTER_TYPED_TEST_SUITE_P(MemFnType, Smoke);
|
||||
|
||||
// clang-format off
|
||||
using MemFnTypes = ::testing::Types<
|
||||
Foo, const Foo>;
|
||||
|
||||
INSTANTIATE_TYPED_TEST_SUITE_P(MemFn, MemFnType, MemFnTypes);
|
||||
// clang-format on
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue