Background
I recently thought about how to create a specific piece of software, and at some point I created the following snippet below:
template <typename ... Mixins>
class Foo : public virtual Mixins... {
};
The idea that I had was the ability to increase the base class with additional properties or behavior depending on the needs of the user. Say that one application should use Foowith an identification number. Perhaps some other application should be able to talk about Foowith color. These needs can be met by adding the following classes:
class HasID {
int m_id = -1;
public:
int getID() { return m_id; }
void assignID(int id) { m_id = id; }
};
class HasColor {
public:
int color = 0;
};
Questions
My two questions about this code are as follows:
- What are the advantages and disadvantages of using such patterns?
- Does this particular template have a name?
Additional Code
, .
:
template <typename Base>
void printBase(std::ostream& out, Base& x) {}
template <>
void printBase(std::ostream& out, HasID& x) {
out << ", ID=" << x.getID();
}
template <>
void printBase(std::ostream& out, HasColor& x) {
out << ", color=" << x.color;
}
template <typename Derived, typename Base, typename ... Bases>
void printBases(std::ostream& out, Derived& x, Base& y) {
printBase(out, y);
printBases<Derived, Bases...>(out, x, x);
}
template <typename Derived>
void printBases(std::ostream& out, Derived& x, Derived& y) {}
template <typename ... Mixins>
std::ostream& operator<<(std::ostream& out, Foo<Mixins...>& x) {
out << "<Foo";
printBases<Foo<Mixins...>, Mixins...>(out, x, x);
return out << '>';
}
Main:
int main()
{
Foo<> plainFoo;
Foo<HasID> fooWithID;
fooWithID.assignID(42);
Foo<HasID, HasColor> multiTalentedFoo;
multiTalentedFoo.assignID(1234);
multiTalentedFoo.color = 0xff0000;
std::cout
<< plainFoo << '\n'
<< fooWithID << '\n'
<< multiTalentedFoo << '\n';
}
:
<Foo>
<Foo, ID=42>
<Foo, ID=1234, color=16711680>