Skip to content

Instantly share code, notes, and snippets.

@mpusz
Created June 18, 2018 20:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mpusz/65316ddbb179a9a92a91e5038ac8d34b to your computer and use it in GitHub Desktop.
Save mpusz/65316ddbb179a9a92a91e5038ac8d34b to your computer and use it in GitHub Desktop.
Simple mixin engine
#include "mixins.h"
#include <iostream>
// members
struct position {
int x;
int y;
};
enum class color {
red,
green,
orange
};
// interfaces
template<typename T>
struct i_get_position : T {
const position &get_position() const { return mixin::get<position>(*this); }
};
template<typename T>
struct i_move : T {
void move(int dx, int dy)
{
auto& [x, y] = mixin::get<position>(*this);
x += dx;
y += dy;
}
};
int main()
{
auto thing = mixin::compose(mixin::interface<i_get_position, i_move>, position{0, 0}, color{color::green});
auto print_position = [](const auto& t){
const auto& pos = t.get_position();
std::cout << "x = " << pos.x << "; y = " << pos.y << "\n";
};
print_position(thing);
thing.move(1, 2);
print_position(thing);
}
#pragma once
#include <tuple>
namespace mixin {
namespace detail {
template<typename ChildType, template<typename> typename... Is>
class composition_impl;
template<typename ChildType, template<typename> typename I, template<typename> typename... Is>
class composition_impl<ChildType, I, Is...> : public I<composition_impl<ChildType, Is...>> {};
template<typename ChildType>
class composition_impl<ChildType> {
protected:
using type = ChildType;
};
}
template<class T, typename ChildType>
constexpr T& get(detail::composition_impl<ChildType>& c) noexcept
{
return std::get<T>(static_cast<ChildType&>(c));
}
template<class T, typename ChildType>
constexpr const T& get(const detail::composition_impl<ChildType>& c) noexcept
{
return std::get<T>(static_cast<const ChildType&>(c));
}
template<template<typename> typename... Is>
struct interface_t {};
template<template<typename> typename... Is>
constexpr interface_t interface = interface_t<Is...>{};
template<typename Interface, typename... Members>
class composition;
template<template<typename> typename... Is, typename... Members>
class composition<interface_t<Is...>, Members...> :
public std::tuple<Members...>,
public detail::composition_impl<composition<interface_t<Is...>, Members...>, Is...>
{
using std::tuple<Members...>::tuple;
};
template<template<typename> typename... Is, typename... Ms>
auto compose(interface_t<Is...>, Ms&&... ms)
{
return composition<interface_t<Is...>, Ms...>{std::forward<Ms>(ms)...};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment