Combine generic and OO techniques to amplify their strengths, not their costs
Reason
Generic and OO techniques are complementary.
Example
Static helps dynamic: Use static polymorphism to implement dynamically polymorphic interfaces.
class Command {
// pure virtual functions
};
// implementations
template</*...*/>
class ConcreteCommand : public Command {
// implement virtuals
};
Example
Dynamic helps static: Offer a generic, comfortable, statically bound interface, but internally dispatch dynamically, so you offer a uniform object layout. Examples include type erasure as with std::shared_ptr's deleter (but don't overuse type erasure).
#include <memory>
class Object {
public:
template<typename T>
Object(T&& obj)
: concept_(std::make_shared<ConcreteCommand<T>>(std::forward<T>(obj))) {}
int get_id() const { return concept_->get_id(); }
private:
struct Command {
virtual ~Command() {}
virtual int get_id() const = 0;
};
template<typename T>
struct ConcreteCommand final : Command {
ConcreteCommand(T&& obj) noexcept : object_(std::forward<T>(obj)) {}
int get_id() const final { return object_.get_id(); }
private:
T object_;
};
std::shared_ptr<Command> concept_;
};
class Bar {
public:
int get_id() const { return 1; }
};
struct Foo {
public:
int get_id() const { return 2; }
};
Object o(Bar{});
Object o2(Foo{});
Note
In a class template, non-virtual functions are only instantiated if they're used -- but virtual functions are instantiated every time. This can bloat code size, and might overconstrain a generic type by instantiating functionality that is never needed. Avoid this, even though the standard-library facets made this mistake.
See also
- ref ???
- ref ???
- ref ???
Enforcement
See the reference to more specific rules.
T.concepts: Concept rules
Concepts is a C++20 facility for specifying requirements for template arguments. They are crucial in the thinking about generic programming and the basis of much work on future C++ libraries (standard and other).
This section assumes concept support
Concept use rule summary:
- T.10: Specify concepts for all template arguments
- T.11: Whenever possible use standard concepts
- T.12: Prefer concept names over
auto - T.13: Prefer the shorthand notation for simple, single-type argument concepts
- ???
Concept definition rule summary:
- T.20: Avoid "concepts" without meaningful semantics
- T.21: Require a complete set of operations for a concept
- T.22: Specify axioms for concepts
- T.23: Differentiate a refined concept from its more general case by adding new use patterns
- T.24: Use tag classes or traits to differentiate concepts that differ only in semantics
- T.25: Avoid complimentary constraints
- T.26: Prefer to define concepts in terms of use-patterns rather than simple syntax
- ???