Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 13 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,16 +256,13 @@ of mixins.
Making an easy concrete class that doesn't need to initialize things:

```cpp
struct concrete : ciabatta::mixin<concrete, stdout_logger, frobnicator> {
};
using concrete = ciabatta::mixin<stdout_logger, frobnicator>;
```

Or maybe something more complicated that does initialize things:
Or maybe something more complicated that needs to initialize things:

```cpp
struct concrete2 : ciabatta::mixin<concrete2, ostream_logger, frobnicator, echoer> {
concrete2(std::ostream& out_) : mixin(out_, "my prefix") {}
};
using concrete2 = ciabatta::mixin<ostream_logger, frobnicator, echoer>;
```

For completeness, the test driver:
Expand All @@ -275,7 +272,7 @@ int main() {
concrete c;
c.frobnicate();

concrete2 c2{std::cerr};
concrete2 c2{std::cerr, "my_prefix"};
c2.frobnicate();
}
```
Expand Down Expand Up @@ -336,8 +333,7 @@ struct is_socket : Base, abstract_socket {
And now we can make our concrete `null_socket` class:

```cpp
struct null_socket
: ciabatta::mixin<null_socket, null_sender, null_receiver, is_socket> {};
using null_socket = ciabatta::mixin<null_sender, null_receiver, is_socket>;
```

*Note:* `is_socket` has to be last if you want the ability to mark member
Expand All @@ -347,11 +343,10 @@ If you don't want to define a new class just to inject an abstract interface,
*ciabatta* has your back:

```cpp
struct null_socket2
: ciabatta::mixin<null_socket2,
null_sender,
null_receiver,
ciabatta::mixins::provides<abstract_socket>::mixin> {};
using null_socket2 = ciabatta::mixin<
null_sender,
null_receiver,
ciabatta::mixins::provides<abstract_socket>::mixin>;
```

### Templated Mixins
Expand All @@ -373,13 +368,10 @@ To use `provides` as-is, we can just supply the `interface` parameter to
`curry`, like so:

```cpp
struct null_socket3
: ciabatta::mixin<
null_socket3,
null_sender,
null_receiver,
ciabatta::curry<provides, abstract_socket>::mixin> {
};
using null_socket3 = ciabatta::mixin<
null_sender,
null_receiver,
ciabatta::curry<ciabatta::mixins::provides, abstract_socket>::mixin>;
```

In fact, this is what `ciabatta::mixins::provides` does with its `mixin`
Expand Down
15 changes: 10 additions & 5 deletions include/ciabatta/ciabatta.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,21 @@ struct chain_inherit<Concrete, H> {
template <typename Concrete, template <class> class... Mixins>
using mixin_impl =
typename chain_inherit<ciabatta_top<Concrete>, Mixins...>::type;

} // namespace detail


template <typename Concrete, template <class> class... Mixins>
struct mixin : ::ciabatta::detail::mixin_impl<Concrete, Mixins...> {
struct mixin_base : ::ciabatta::detail::mixin_impl<Concrete, Mixins...> {
template <typename... Rest>
constexpr mixin(Rest&&... rest)
constexpr mixin_base(Rest&&... rest)
: ::ciabatta::detail::mixin_impl<Concrete, Mixins...>(
static_cast<decltype(rest)>(rest)...) {}
};

} // namespace detail

template <template <class> class... Mixins>
struct mixin : ::ciabatta::detail::mixin_base<mixin<Mixins...>, Mixins...> {
using ciabatta::detail::mixin_base<mixin<Mixins...>, Mixins...>::mixin_base;

mixin() = default;
mixin(mixin const&) = default;
mixin(mixin&&) = default;
Expand Down
11 changes: 5 additions & 6 deletions test/example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,15 @@ struct frobnicator : Base {

void frobnicate() const { this->self().log("frobnicate."); }
};
struct concrete : ciabatta::mixin<concrete, stdout_logger, frobnicator> {};
struct concrete2
: ciabatta::mixin<concrete2, ostream_logger, frobnicator, echoer> {
concrete2(std::ostream& out_) : mixin(out_, "my prefix") {}
};

using concrete = ciabatta::mixin<stdout_logger, frobnicator>;

using concrete2 = ciabatta::mixin<ostream_logger, frobnicator, echoer>;

int main() {
concrete c;
c.frobnicate();

concrete2 c2{std::cerr};
concrete2 c2{std::cerr, "my_prefix"};
c2.frobnicate();
}
5 changes: 1 addition & 4 deletions test/test_chained_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ struct fragment_b : B {
int w;
};

struct composite : ciabatta::mixin<composite, fragment_a, fragment_b> {
constexpr composite(arg1 a1, arg2 a2, arg3 a3, arg4 a4)
: mixin(a1, a2, a3, a4) {}
};
using composite = ciabatta::mixin<fragment_a, fragment_b>;

} // namespace test_chained_init

Expand Down
27 changes: 11 additions & 16 deletions test/test_provides.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,17 @@ struct is_socket : Base, abstract_socket {
CIABATTA_DEFAULT_MIXIN_CTOR(is_socket, Base);
};

struct null_socket
: ciabatta::mixin<null_socket, null_sender, null_receiver, is_socket> {};

struct null_socket2
: ciabatta::mixin<null_socket2,
null_sender,
null_receiver,
ciabatta::mixins::provides<abstract_socket>::mixin> {};

struct null_socket3
: ciabatta::mixin<
null_socket3,
null_sender,
null_receiver,
ciabatta::curry<ciabatta::mixins::provides, abstract_socket>::mixin> {
};
using null_socket = ciabatta::mixin<null_sender, null_receiver, is_socket>;

using null_socket2 = ciabatta::mixin<
null_sender,
null_receiver,
ciabatta::mixins::provides<abstract_socket>::mixin>;

using null_socket3 = ciabatta::mixin<
null_sender,
null_receiver,
ciabatta::curry<ciabatta::mixins::provides, abstract_socket>::mixin>;

int main() {
null_socket s1;
Expand Down