Skip to content

Commit

Permalink
rework 'override'
Browse files Browse the repository at this point in the history
  • Loading branch information
jll63 committed Sep 28, 2024
1 parent 64a1ed5 commit 768c198
Show file tree
Hide file tree
Showing 15 changed files with 102 additions and 107 deletions.
32 changes: 17 additions & 15 deletions docs.in/reference/method.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***
entry: method
hrefs: method-fn, method-next_type, method-override_fn, method-override, method-use_next
hrefs: method-fn, method-next_type, method-override, method-override, method-use_next
headers: yorel/yomm2/core.hpp, yorel/yomm2.hpp
```c++
Expand All @@ -16,7 +16,7 @@ struct method<Name, ReturnType(Args...), Policy>;
`method` provides a static function object, `fn`, that takes a list of arguments
of type `Args`, *minus* the `virtual_` decorator, and returns `ReturnType`.
Method definitions can be added with the [`method::override_fn`](#override_fn)
Method definitions can be added with the [`method::override`](#override)
and [`method::override`](#override) class templates.
## Template parameters
Expand Down Expand Up @@ -82,17 +82,17 @@ The single instance of `method<Name, ReturnType(Args...)>`. Used to call the met
| Name | Description |
| --------------------------------- | --------------------------------------------------------- |
| [override_fn](#override_fn) | add a definition to the method |
| [override](#override) | add a definition to the method |
| [override](#override) | add a definition container to the method |
| [next_type](#next_type) | type of a pointer to the next most specialised definition |
| [use_next](#use_next) | CRTP base for definitions that use `next` |
## override_fn
## override
```c++
template<auto Function>
struct override_fn {
explicit override_fn(next_type* next = nullptr);
struct override {
explicit override(next_type* next = nullptr);
};
```
Expand Down Expand Up @@ -200,18 +200,18 @@ using kick = yomm2::method<kick_methods(virtual_<Animal&>), std::string>;
std::string kick_cat(Cat& dog) {
return "hiss";
}
YOMM2_REGISTER(kick::override_fn<kick_cat>);
YOMM2_REGISTER(kick::override<kick_cat>);

std::string kick_dog(Dog& dog) {
return "bark";
}
YOMM2_REGISTER(kick::override_fn<kick_dog>);

struct kick_bulldog {
static std::string fn(Bulldog& dog) {
return kick::next<fn>(dog) + " and bite";
}
};
YOMM2_REGISTER(kick::override<kick_dog>);

std::string kick_bulldog(Bulldog& dog) {
return kick::next<kick_bulldog>(dog) + " and bite";
}

YOMM2_REGISTER(kick::override<kick_bulldog>);

struct YOMM2_METHOD_NAME(pet); // use obfuscated name
Expand All @@ -221,12 +221,14 @@ using pet =
std::string pet_cat(Cat& dog) {
return "purr";
}
YOMM2_REGISTER(pet::override_fn<pet_cat>);

YOMM2_REGISTER(pet::override<pet_cat>);

std::string pet_dog(Dog& dog) {
return "wag tail";
}
YOMM2_REGISTER(pet::override_fn<pet_dog>);

YOMM2_REGISTER(pet::override<pet_dog>);

BOOST_AUTO_TEST_CASE(ref_method_example) {
yomm2::initialize();
Expand Down
2 changes: 1 addition & 1 deletion docs.in/reference/use_definitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ using same_type = method<same_type_(
bool same_type_catch_all(const abstract_matrix&, const abstract_matrix&) {
return false;
}
YOMM2_REGISTER(same_type::override_fn<same_type_catch_all>);
YOMM2_REGISTER(same_type::override<same_type_catch_all>);

// 2
template<class Method, typename...>
Expand Down
26 changes: 11 additions & 15 deletions docs.in/tutorials/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ std::string kick_dog(Dog& dog) {
return "bark";
}

kick::override_fn<kick_dog> add_kick_dog;
kick::override<kick_dog> add_kick_dog;
// >

// md<
Expand All @@ -120,7 +120,7 @@ kick::override_fn<kick_dog> add_kick_dog;
// appropriate function. Function templates and explicit specialization can also
// be used for this purpose.

// What about `next`? The constructor of `override_fn` can be passed a pointer
// What about `next`? The constructor of `override` can be passed a pointer
// to a function that will be set to the function's next definition by
// `update`. The pointer type is available in the method as `next_type`.

Expand All @@ -131,7 +131,7 @@ std::string kick_bulldog(Bulldog& dog) {
return kick::next<kick_bulldog>(dog) + " and bite back";
}

kick::override_fn<kick_bulldog> add_kick_bulldog;
kick::override<kick_bulldog> add_kick_bulldog;
// >

// md<
Expand Down Expand Up @@ -174,7 +174,7 @@ BOOST_AUTO_TEST_CASE(test_synopsis_functions_no_macros) {
// passing it `declval` arguments for the definition's parameter list. The
// compiler performs overload resolution, and the macro uses `decltype` to
// extract the result type, i.e the method's class, and registers the definition
// and the `next` pointer with `override_fn`.
// and the `next` pointer with `override`.

// In the process, both macros need to create identifiers for the various static
// objects, and the name of the function inside the definition wrapper class.
Expand Down Expand Up @@ -247,7 +247,7 @@ using kick = method<kick_(virtual_<Animal&>), std::string>;

// md<

// `override_fn` is a workhorse that is intended to be used directly only by
// `override` is a workhorse that is intended to be used directly only by
// `define_method`. YOMM2 has another mechanism that is a bit more high level:
// *definition containers*.

Expand All @@ -258,11 +258,9 @@ using kick = method<kick_(virtual_<Animal&>), std::string>;
// >

// code<
struct kick_dog {
static std::string fn(Dog& dog) {
return "bark";
}
};
std::string kick_dog(Dog& dog) {
return "bark";
}

YOMM2_REGISTER(kick::override<kick_dog>);
// >
Expand All @@ -279,11 +277,9 @@ YOMM2_REGISTER(kick::override<kick_dog>);
// >

// code<
struct kick_bulldog {
static std::string fn(Bulldog& dog) {
return kick::next<fn>(dog) + " and bite back";
}
};
static std::string kick_bulldog(Bulldog& dog) {
return kick::next<kick_bulldog>(dog) + " and bite back";
}

YOMM2_REGISTER(kick::override<kick_bulldog>);
// >
Expand Down
2 changes: 1 addition & 1 deletion docs.in/tutorials/templates_tutorial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ inline bool operator==(const vector& a, const vector& b) {
// Now we need to provide definitions for these methods. But which ones?

// We could decide *for the user* that only (say) vectors of `double`s and
// `int`s are supported. We could use `override_fn` or `override` to
// `int`s are supported. We could use `override` or `override` to
// define four specializations, covering all the possible combinations (i.e. the
// Cartesian product):

Expand Down
12 changes: 5 additions & 7 deletions examples/slides.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,17 +188,15 @@ using value = method<value_id(virtual_<const Node&>), int>;
int number_value(const Number& node) {
return node.val;
}
value::override_fn<number_value> add_number_value;
value::override<number_value> add_number_value;

template<class NodeClass, class Op>
struct binary_value {
static int fn(const NodeClass& expr) {
int binary_op(const NodeClass& expr) {
return Op()(value::fn(expr.left), value::fn(expr.right));
}
};
}

YOMM2_REGISTER(value::override<binary_value<Plus, std::plus<int>>>);
YOMM2_REGISTER(value::override<binary_value<Times, std::multiplies<int>>>);
YOMM2_REGISTER(value::override<binary_op<Plus, std::plus<int>>>);
YOMM2_REGISTER(value::override<binary_op<Times, std::multiplies<int>>>);

}

Expand Down
34 changes: 12 additions & 22 deletions include/yorel/yomm2/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,44 +647,34 @@ class method<Name(Parameters...), Return, Policy> : public detail::method_info {
};

template<auto Function>
struct override_fn_impl {
explicit override_fn_impl(FunctionPointer* next = nullptr);
struct override_impl {
explicit override_impl(FunctionPointer* next = nullptr);
};

template<auto Function, typename FunctionType>
struct override_fn_aux;
struct override_aux;

template<auto Function, typename FnReturnType, typename... FnParameters>
struct override_fn_aux<Function, FnReturnType (*)(FnParameters...)>
: override_fn_impl<Function> {
struct override_aux<Function, FnReturnType (*)(FnParameters...)>
: override_impl<Function> {
};

template<
auto Function, class FnClass, typename FnReturnType,
typename... FnParameters>
struct override_fn_aux<
struct override_aux<
Function, FnReturnType (FnClass::*)(FnParameters...)> {
static auto fn(FnClass* this_, FnParameters&&... args) -> FnReturnType {
return (this_->*Function)(std::forward<FnParameters>(args)...);
}

override_fn_impl<fn> impl{&next<Function>};
override_impl<fn> impl{&next<Function>};
};

public:
template<auto Function>
struct override_fn : override_fn_aux<Function, decltype(Function)> {
using override_fn_aux<Function, decltype(Function)>::override_fn_aux;
};

template<auto... F>
struct override_fns {
std::tuple<override_fn<F>...> fns;
};

template<class Container>
struct override : override_fn<Container::fn> {
using type = override;
template<auto... Function>
struct override {
std::tuple<override_aux<Function, decltype(Function)>...> impl;
};
};

Expand Down Expand Up @@ -988,8 +978,8 @@ auto method<Name(Parameters...), Return, Policy>::

template<typename Name, typename Return, typename... Parameters, class Policy>
template<auto Function>
method<Name(Parameters...), Return, Policy>::override_fn_impl<
Function>::override_fn_impl(FunctionPointer* p_next) {
method<Name(Parameters...), Return, Policy>::override_impl<
Function>::override_impl(FunctionPointer* p_next) {
// Work around MSVC bug: using &next<Function> as a default value
// for 'next' confuses it about Parameters not being expanded.
if (!p_next) {
Expand Down
2 changes: 1 addition & 1 deletion include/yorel/yomm2/macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
}; \
INLINE YOMM2_REGISTER( \
OVERRIDERS<YOREL_YOMM2_DETAIL_RETURN_TYPE(__VA_ARGS__) ARGS>:: \
method_type::override_fn<OVERRIDERS< \
method_type::override<OVERRIDERS< \
YOREL_YOMM2_DETAIL_RETURN_TYPE(__VA_ARGS__) ARGS>::fn>); \
INLINE auto \
OVERRIDERS<YOREL_YOMM2_DETAIL_RETURN_TYPE(__VA_ARGS__) ARGS>::fn ARGS \
Expand Down
4 changes: 2 additions & 2 deletions include/yorel/yomm2/templates.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,12 @@ struct use_definition {

template<typename T>
struct impl<true, T> {
using type = typename T::method::template override<T>;
using type = typename T::method::template override<T::fn>;
};

template<typename First, typename... Rest>
struct impl<false, Definition<First, Rest...>> {
using type = typename First::template override<Definition<First, Rest...>>;
using type = typename First::template override<Definition<First, Rest...>::fn>;
};

template<typename TypeList>
Expand Down
24 changes: 12 additions & 12 deletions tests/benchmarks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,24 +377,24 @@ struct population : abstract_population {
template<typename T>
static void fn1(T&) {
}
typename method1::template override_fn<fn1<intermediate<0>>>
typename method1::template override<fn1<intermediate<0>>>
YOMM2_GENSYM;
typename method1::template override_fn<fn1<intermediate<1>>>
typename method1::template override<fn1<intermediate<1>>>
YOMM2_GENSYM;

template<typename T, typename U>
static void fn2(T&, U&) {
}
typename method2::template override_fn<
typename method2::template override<
fn2<intermediate<0>, intermediate<0>>>
YOMM2_GENSYM;
typename method2::template override_fn<
typename method2::template override<
fn2<intermediate<0>, intermediate<1>>>
YOMM2_GENSYM;
typename method2::template override_fn<
typename method2::template override<
fn2<intermediate<1>, intermediate<0>>>
YOMM2_GENSYM;
typename method2::template override_fn<
typename method2::template override<
fn2<intermediate<1>, intermediate<1>>>
YOMM2_GENSYM;
};
Expand All @@ -416,24 +416,24 @@ struct population : abstract_population {
template<typename T>
static void fn1(vptr<T>) {
}
typename method1::template override_fn<fn1<intermediate<0>>>
typename method1::template override<fn1<intermediate<0>>>
YOMM2_GENSYM;
typename method1::template override_fn<fn1<intermediate<1>>>
typename method1::template override<fn1<intermediate<1>>>
YOMM2_GENSYM;

template<typename T, typename U>
static void fn2(vptr<T>, vptr<U>) {
}
typename method2::template override_fn<
typename method2::template override<
fn2<intermediate<0>, intermediate<0>>>
YOMM2_GENSYM;
typename method2::template override_fn<
typename method2::template override<
fn2<intermediate<0>, intermediate<1>>>
YOMM2_GENSYM;
typename method2::template override_fn<
typename method2::template override<
fn2<intermediate<1>, intermediate<0>>>
YOMM2_GENSYM;
typename method2::template override_fn<
typename method2::template override<
fn2<intermediate<1>, intermediate<1>>>
YOMM2_GENSYM;
};
Expand Down
Loading

0 comments on commit 768c198

Please sign in to comment.