Skip to content

Instantly share code, notes, and snippets.

@JPGygax68
Last active May 17, 2016 21:48
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 JPGygax68/60ac92af682da4b772ae12a4149cc89b to your computer and use it in GitHub Desktop.
Save JPGygax68/60ac92af682da4b772ae12a4149cc89b to your computer and use it in GitHub Desktop.
#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