Last active
May 17, 2016 21:48
-
-
Save JPGygax68/60ac92af682da4b772ae12a4149cc89b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
/*======================================================================= | |
* ASPECT COMPOSITION | |
*======================================================================*/ | |
/* This is the base class to be specialized via CRTP. | |
* | |
* It must provide all the methods that aspects can override as no-ops. | |
*/ | |
template<class Class> | |
struct Base | |
{ | |
void tell() {} // no-op, and ends the chain | |
protected: | |
// This is a con | |
auto p() { return static_cast<Class*>(this); } | |
}; | |
/** The aspect composer is a template that uses a classic head/tail setup to recursively | |
inherit from all specified ancestors (= aspects). | |
*/ | |
template<class Class, template<class> class ...Aspects> class Aspect_composer; | |
template<class Class, template<class> class Aspect> | |
class Aspect_composer<Class, Aspect>: public Aspect< Base<Class> > {}; | |
template<class Class, template<class> class FirstAspect, template<class> class ...OtherAspects> | |
class Aspect_composer<Class, FirstAspect, OtherAspects...>: public FirstAspect< Aspect_composer<Class, OtherAspects...> > {}; | |
/** Here now come the aspects. | |
*/ | |
template<class Parent> | |
class Aspect1: public Parent | |
{ | |
public: | |
Aspect1() { std::cout << "Aspect1 here" << std::endl; } | |
void tell() { | |
auto that = this->p(); | |
std::cout << "Hello from Aspect1: dummy = " << that->dummy << std::endl; | |
Parent::tell(); // chaining to next aspect | |
} | |
}; | |
template<class Parent> | |
class Aspect2: public Parent | |
{ | |
public: | |
Aspect2() { std::cout << "Aspect2 here" << std::endl; } | |
void tell() { | |
auto that = this->p(); | |
std::cout << "Hello from Aspect2: dummy = " << that->dummy << std::endl; | |
Parent::tell(); // chaining | |
} | |
}; | |
template<class Parent> | |
class Aspect3: public Parent | |
{ | |
public: | |
Aspect3() { std::cout << "Aspect3 here" << std::endl; } | |
void tell() { | |
std::cout << "Hello from Aspect3" << std::endl; | |
Parent::tell(); // chaining | |
} | |
}; | |
/** Declaring a class that integrates all the aspects is now easy: | |
*/ | |
class My_class: public Aspect_composer<My_class, Aspect1, Aspect2, Aspect3> | |
{ | |
private: | |
// Every aspect that is supposed to access private/protected stuff must be given access explicitly: | |
friend class Aspect1; | |
friend class Aspect2; | |
int dummy = 100; | |
}; | |
int main() | |
{ | |
My_class obj; | |
obj.tell(); | |
std::cout << std::endl << "Press RETURN to terminate" << std::endl; | |
char dummy; std::cin >> std::noskipws >> dummy; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment