The special-member toolkit: =default, =delete, explicit single-arg constructors, override/final, delegating constructors. Deleted copies become the way to spell entity types.
class Mixer {
public:
explicit Mixer(Config c);
Mixer(const Mixer&) = delete;
Mixer& operator=(const Mixer&) = delete;
Mixer(Mixer&&) noexcept = default;
~Mixer() override;
};
No structural change — C++14 is a defect-fix release for class authors; deprecated attribute helps API evolution.
The hidden-friend idiom becomes standard practice: define operators as friends inside the class so they are found only by ADL, shrinking overload sets and improving errors. [[nodiscard]] guards factories.
class Price {
friend bool operator==(Price a, Price b)
{ return a.cents_ == b.cents_; }
long long cents_;
public:
[[nodiscard]] static Price from_cents(long long c);
};
Comparison boilerplate dies: default <=> (and ==). explicit(bool) makes conditionally-explicit wrappers writable; [[no_unique_address]] stores empty policies for free.
struct Extent {
int w{}, h{};
friend auto operator<=>(const Extent&, const Extent&) = default;
};
template <class T, class Alloc>
class Box {
[[no_unique_address]] Alloc alloc_;
};
Deducing this collapses const/ref-qualified getter quartets into one template and enables CRTP-free mixins; static operator() makes stateless function objects honest.
struct Builder {
template <class Self>
Self&& with_title(this Self&& self, std::string t)
{ self.title_ = std::move(t); return std::forward<Self>(self); }
};
= delete("reason") documents the why at the call site, contracts (pre/post) move preconditions out of comments, and reflection starts generating the remaining boilerplate.
void use(Session&) = delete("Session is single-owner: pass by value");
int pop() pre(!empty()) post(r : r >= 0);
C++29direction · not adopted
Direction: reflection-based code generation (token injection, P3294 line of work) targets generating members, not just reading them — the end of hand-written builders and bindings.