Skip to content

Commit

Permalink
more macro work
Browse files Browse the repository at this point in the history
  • Loading branch information
jll63 committed Sep 21, 2024
1 parent cf7aecf commit c87e03f
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 23 deletions.
23 changes: 13 additions & 10 deletions docs.in/reference/declare_static_method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ headers: yorel/yomm2/cute.hpp, yorel/yomm2.hpp
hrefs: YOMM2_STATIC_DECLARE

```c++
#define declare_static_method(name, (types), return-type) /*unspecified*/
#define declare_static_method(name, (types), return -type) /*unspecified*/
```

Declare a method as a static member in a `struct` or `class`. Otherwise, the
Expand All @@ -29,43 +29,46 @@ create functions that can be picked via ADL.
#include <yorel/yomm2.hpp>
#include <yorel/yomm2/compiler.hpp>

struct Engineer { virtual ~Engineer() {} };
struct Engineer {
virtual ~Engineer() {
}
};
struct SeniorEngineer : Engineer {};

register_classes(Engineer, SeniorEngineer);

declare_method(speak, (virtual_<const Engineer&>), std::string);

define_method(speak, (const Engineer&), std::string) {
return "engineers love ADL";
return "engineers love ADL";
}

define_method(speak, (const SeniorEngineer& engineer), std::string) {
return "senior " + next(engineer);
return "senior " + next(engineer);
}

struct no_adl {
declare_static_method(speak, (virtual_<const Engineer&>), std::string);
};

define_method(no_adl::speak, (const Engineer&), std::string) {
return "engineers hate ADL";
return "engineers hate ADL";
}

define_method(no_adl::speak, (const SeniorEngineer& engineer), std::string) {
return "senior " + next(engineer);
return "senior " + next(engineer);
}

BOOST_AUTO_TEST_CASE(ref_love_adl) {
yorel::yomm2::initialize();

{
const Engineer &engineer = Engineer();
const Engineer& engineer = Engineer();
BOOST_TEST(speak(engineer) == "engineers love ADL");
}

{
const Engineer &engineer = SeniorEngineer();
const Engineer& engineer = SeniorEngineer();
BOOST_TEST(speak(engineer) == "senior engineers love ADL");
}
}
Expand All @@ -74,12 +77,12 @@ BOOST_AUTO_TEST_CASE(ref_hate_adl) {
yorel::yomm2::initialize();

{
const Engineer &engineer = Engineer();
const Engineer& engineer = Engineer();
BOOST_TEST(no_adl::speak(engineer) == "engineers hate ADL");
}

{
const Engineer &engineer = SeniorEngineer();
const Engineer& engineer = SeniorEngineer();
BOOST_TEST(no_adl::speak(engineer) == "senior engineers hate ADL");
}
}
Expand Down
36 changes: 23 additions & 13 deletions include/yorel/yomm2/macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@
#define yOMM2_WHEN_STATIC(CODE1, CODE2) CODE1
#define yOMM2_WHEN_NOT_STATIC(CODE1, CODE2) CODE2

#define yOMM2_OPEN_BRACE {
#define yOMM2_CLOSE_BRACE }

#define yOMM2_SELECTOR(NAME) NAME##_yOMM2_selector_

// Find method given the arguments. We cannot detect if __VAR_ARGS__ is empty,
// so we cannot express the 'method<...>' type directly. Instead, we wrap
// __VAR_ARGS__ in 'types<...>' and use 'method_va_args_first' find the method.

#define yOMM2_method(NAME, ARGS, ...) \
::yorel::yomm2::method<YOMM2_SYMBOL(NAME) ARGS, __VA_ARGS__>

#define YOMM2_DECLARE(NAME, ARGS, ...) \
yOMM2_DECLARE(yOMM2_WHEN_NOT_STATIC, NAME, ARGS, __VA_ARGS__)

Expand All @@ -46,13 +58,12 @@
#define yOMM2_DECLARE(IF_STATIC, NAME, ARGS, ...) \
struct YOMM2_SYMBOL(NAME); \
IF_STATIC(static, ) \
::yorel::yomm2::method<YOMM2_SYMBOL(NAME) ARGS, __VA_ARGS__> \
yorel_yomm2_detail_##NAME##_guide( \
BOOST_PP_REPEAT(BOOST_PP_TUPLE_SIZE(ARGS), yOMM2_PLIST, ARGS)); \
yOMM2_method(NAME, ARGS, __VA_ARGS__) yOMM2_SELECTOR(NAME)( \
BOOST_PP_REPEAT(BOOST_PP_TUPLE_SIZE(ARGS), yOMM2_PLIST, ARGS)); \
IF_STATIC(static, ) \
inline decltype(auto) NAME( \
BOOST_PP_REPEAT(BOOST_PP_TUPLE_SIZE(ARGS), yOMM2_PLIST, ARGS)) { \
return ::yorel::yomm2::method<YOMM2_SYMBOL(NAME) ARGS, __VA_ARGS__>::fn( \
return yOMM2_method(NAME, ARGS, __VA_ARGS__)::fn( \
BOOST_PP_REPEAT(BOOST_PP_TUPLE_SIZE(ARGS), yOMM2_ALIST, ARGS)); \
}

Expand All @@ -68,22 +79,21 @@
struct _yOMM2_select; \
template<typename... A> \
struct _yOMM2_select<void(A...)> { \
using type = \
decltype(yorel_yomm2_detail_##NAME##_guide(std::declval<A>()...)); \
using type = decltype(yOMM2_SELECTOR(NAME)(std::declval<A>()...)); \
}; \
using _yOMM2_method = _yOMM2_select<void ARGS>::type; \
using _yOMM2_return_t = _yOMM2_method::return_type;
using method_type = _yOMM2_select<void ARGS>::type; \
using _yOMM2_return_t = method_type::return_type;

#define yOMM2_DEFINE(NS, NAME, ARGS, ...) \
namespace { \
namespace NS { \
yOMM2_SELECT_METHOD(NAME, ARGS); \
_yOMM2_method::next_type next; \
method_type::next_type next; \
struct _yOMM2_spec { \
static boost::mp11::mp_first<boost::mp11::mp_list<__VA_ARGS__>> \
yOMM2_body ARGS; \
}; \
_yOMM2_method::override_fn<_yOMM2_spec::yOMM2_body> YOMM2_GENSYM(&next); \
method_type::override_fn<_yOMM2_spec::yOMM2_body> YOMM2_GENSYM(&next); \
} \
} \
boost::mp11::mp_first<boost::mp11::mp_list<__VA_ARGS__>> \
Expand All @@ -104,15 +114,15 @@
template<> \
struct CONTAINER< \
boost::mp11::mp_first<boost::mp11::mp_list<__VA_ARGS__>> ARGS> { \
static NS::_yOMM2_method::next_type next; \
static NS::method_type::next_type next; \
static boost::mp11::mp_first<boost::mp11::mp_list<__VA_ARGS__>> fn \
ARGS; \
}; \
INLINE NS::_yOMM2_method::next_type CONTAINER< \
INLINE NS::method_type::next_type CONTAINER< \
boost::mp11::mp_first<boost::mp11::mp_list<__VA_ARGS__>>(ARGS)>::next; \
namespace { \
namespace NS { \
INLINE _yOMM2_method::override_fn<CONTAINER< \
INLINE method_type::override_fn<CONTAINER< \
boost::mp11::mp_first<boost::mp11::mp_list<__VA_ARGS__>> ARGS>::fn> \
YOMM2_GENSYM( \
&CONTAINER< \
Expand Down

0 comments on commit c87e03f

Please sign in to comment.