template<typename T>structColoredShape: T
{
static_assert(is_base_of<Shape, T>::value,
"Tempalte argument must be a Shape");
string color;
string str() constoverride {
ostringstream oss;
oss << T::str() <<" has the color "<< color;
return oss.str();
}
template<typename...Args> ColoredShape(const string& color, Args ...args)
: T(std::forward<Args>(args)...), color{ color } {}
};
Funtional Decorator
template<typename>classLogger;
template<typename R, typename... Args>structLogger<R(Args...)> {
Logger(function<R(Args...)> func, const string& name)
: func{func}, name{name} {}
R operator() (Args ...args)
{
cout <<"Enter "<< name << endl;
R result = func(args...);
cout <<"Exiting "<< name << endl;
return result;
}
function<R(Args ...)> func;
string name;
};
template<typename R, typename... Args>auto make_logger(R (*func)(Args...), const string& name)
{
return Logger<R(Args...)>(
function<R(Args...)>(func),
name);
}
auto logged_add = make_logger(add, "add");
auto result = logged_add(2, 3);
Summary
Dynamic Decorator
Store decoreated object, compose dynamically in runtime. However, original object member cannot access member variable.
Static Decorator
Using mixin inheritance, compose in compile time. So, this method cannot compose again in runtime. However, it can access member variable. And using constructor forwarding, completely initialize object.
Functional Decorator
Can overwrap a code block or other specific function to compose.