Skip to content

Instantly share code, notes, and snippets.

@caiorss
Forked from langthom/Mixin.cc
Created October 17, 2018 17:25
Show Gist options
  • Save caiorss/f48bfff244e35ba05980f3b466941757 to your computer and use it in GitHub Desktop.
Save caiorss/f48bfff244e35ba05980f3b466941757 to your computer and use it in GitHub Desktop.
Exemplary demonstration of how Mixins could be implemented in C++.
// Simple mixins in C++. Thomas Lang, 2018.
#include <iostream>
#include <list>
namespace {
// add const reference to type.
template<typename T>
struct add_cref : std::add_lvalue_reference<std::add_const<T> > {};
// calculate F /\ G
template<bool F, bool G>
struct AND : std::false_type {};
template<>
struct AND<true, true> : std::true_type {};
}
// Base class, a simple queue with no special features.
template<typename ElementType>
class BaseQueue {
protected:
typedef ElementType ArgumentType;
public:
BaseQueue() = default;
~BaseQueue() = default;
ElementType pop(void) {
ElementType frontCopy = *_queue.begin();
_queue.pop_front();
return frontCopy;
}
virtual void push(ElementType arg) {
_queue.push_back(arg);
}
template<typename T>
friend std::ostream& operator<<(std::ostream&, const BaseQueue<T>&);
private:
std::list<ElementType> _queue;
};
template<typename ElementType>
std::ostream& operator<<(std::ostream& out, const BaseQueue<ElementType>& queue) {
out << "[";
for (auto it = queue._queue.begin(); it != queue._queue.end(); ++it) {
if (it != queue._queue.begin()) out << ",";
out << *it;
}
out << "]";
return out;
}
// Feature #1: Increment each value by 1 on pushing.
template<typename Base>
class Incrementing : public Base {
public:
virtual void push(typename Base::ArgumentType arg) override {
arg += 1;
Base::push(arg);
}
};
// Feature #2: Double each value on pushing.
template<typename Base>
class Doubling : public Base {
public:
virtual void push(typename Base::ArgumentType arg) override {
arg *= 2;
Base::push(arg);
}
};
int main(void) {
BaseQueue<int> base; // A regular queue.
Incrementing<BaseQueue<int>> incr; // A queue with the incrementing feature
Doubling<Incrementing<BaseQueue<int> > > sepp1; // A queue with incrementing and doubling feature.
Incrementing<Doubling<BaseQueue<int> > > sepp2; // A queue with doubling and incrementing feature.
for (unsigned int i = 0; i < 4; ++i) {
base.push(i);
incr.push(i);
sepp1.push(i);
sepp2.push(i);
}
std::cout << "Base queue: (\\i -> i) " << base << std::endl;
std::cout << "Incrementor queue: (\\i -> i + 1) " << incr << std::endl;
std::cout << "complex1 queue: (\\i -> 2*i + 1) " << sepp1 << std::endl;
std::cout << "complex2 queue: (\\i -> (i+1) * 2) " << sepp2 << std::endl;
std::cout << std::endl;
// -------------------------
for (unsigned int i = 0; i < 3; ++i) {
base.pop();
incr.pop();
sepp1.pop();
sepp2.pop();
}
std::cout << "Popping 3 times, result: (base) " << base << std::endl;
std::cout << "Popping 3 times, result: (incr) " << incr << std::endl;
std::cout << "Popping 3 times, result: (sepp1) " << sepp1 << std::endl;
std::cout << "Popping 3 times, result: (sepp2) " << sepp2 << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment