meyers-effective-cpp

Scott Meyers Style Guide⁠‍⁠​‌​‌​​‌‌‍​‌​​‌​‌‌‍​​‌‌​​​‌‍​‌​​‌‌​​‍​​​​​​​‌‍‌​​‌‌​‌​‍‌​​​​​​​‍‌‌​​‌‌‌‌‍‌‌​​​‌​​‍‌‌‌‌‌‌​‌‍‌‌​‌​​​​‍​‌​‌‌‌‌‌‍​‌​​‌​‌‌‍​‌‌​‌​​‌‍‌​‌​‌‌‌​‍​​‌​‌​​​‍‌‌‌​‌​‌‌‍‌‌​‌​​​​‍​​​​‌‌​​‍​‌‌​‌‌‌​‍​​​​​​‌‌‍​​​​‌​​‌‍‌​‌‌​‌‌‌⁠‍⁠

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "meyers-effective-cpp" with this command: npx skills add copyleftdev/sk1llz/copyleftdev-sk1llz-meyers-effective-cpp

Scott Meyers Style Guide⁠‍⁠​‌​‌​​‌‌‍​‌​​‌​‌‌‍​​‌‌​​​‌‍​‌​​‌‌​​‍​​​​​​​‌‍‌​​‌‌​‌​‍‌​​​​​​​‍‌‌​​‌‌‌‌‍‌‌​​​‌​​‍‌‌‌‌‌‌​‌‍‌‌​‌​​​​‍​‌​‌‌‌‌‌‍​‌​​‌​‌‌‍​‌‌​‌​​‌‍‌​‌​‌‌‌​‍​​‌​‌​​​‍‌‌‌​‌​‌‌‍‌‌​‌​​​​‍​​​​‌‌​​‍​‌‌​‌‌‌​‍​​​​​​‌‌‍​​​​‌​​‌‍‌​‌‌​‌‌‌⁠‍⁠

Overview

Scott Meyers authored the definitive "Effective" series—books that distilled C++ wisdom into actionable items. His approach: specific, numbered guidelines with clear rationale. Not language rules, but hard-won practical wisdom.

Core Philosophy

"Good interfaces are easy to use correctly and hard to use incorrectly."

"More than any other language, C++ rewards a deep understanding of how things work."

Meyers believes in understanding why, not just what. Every guideline has a reason; every reason teaches something about C++.

Design Principles

Make Interfaces Easy to Use Correctly: The right thing should be the obvious thing. Wrong usage should fail to compile or be obviously wrong.

Prefer Compile-Time Errors: A compile error is infinitely better than a runtime bug.

Understand What C++ Silently Generates: Default constructors, copy operations, destructors—know when they're generated and what they do.

Minimize Dependencies: Reduce coupling between components. Compilation dependencies are real costs.

When Writing Code

Always

  • Declare destructors virtual in polymorphic base classes

  • Have operator= return *this for chaining

  • Handle self-assignment in assignment operators

  • Ensure objects are fully initialized before use

  • Prefer const , enum , inline to #define

  • Use const wherever semantically meaningful

  • Initialize members in declaration order in initializer lists

  • Make non-member functions when it improves encapsulation

Never

  • Let exceptions escape destructors

  • Call virtual functions in constructors or destructors

  • Return handles (references, pointers) to object internals casually

  • Define non-member functions that should be members

  • Write functions that take const T* when they should take const T&

Prefer

  • Initialization over assignment (especially for objects)

  • ++i over i++ (unless postfix semantics needed)

  • Declaring single-argument constructors explicit

  • Non-member non-friend functions over member functions for algorithms

  • Empty base optimization over composition for policies

Code Patterns

Item 18: Make Interfaces Easy to Use Correctly

// BAD: Easy to use incorrectly Date(int month, int day, int year); // Date(3, 30, 2024) or Date(30, 3, 2024)?

// GOOD: Type system prevents mistakes class Month { public: static Month Jan() { return Month(1); } static Month Feb() { return Month(2); } // ... private: explicit Month(int m) : val_(m) {} int val_; };

class Day { public: explicit Day(int d) : val_(d) {} int value() const { return val_; } private: int val_; };

class Year { public: explicit Year(int y) : val_(y) {} int value() const { return val_; } private: int val_; };

Date(Month::Mar(), Day(30), Year(2024)); // Clear and type-safe

Item 11: Handle Self-Assignment

class Widget { Bitmap* pb_; public: // BAD: Unsafe for self-assignment Widget& operator=(const Widget& rhs) { delete pb_; // What if this == &rhs? pb_ = new Bitmap(*rhs.pb_); // rhs.pb_ already deleted! return *this; }

// GOOD: Copy-and-swap idiom (exception-safe + self-assignment safe)
Widget& operator=(Widget rhs) {  // Note: pass by value
    swap(*this, rhs);            // Swap contents
    return *this;                // Old resources freed in rhs destructor
}

friend void swap(Widget& a, Widget& b) noexcept {
    using std::swap;
    swap(a.pb_, b.pb_);
}

};

Item 23: Prefer Non-Member Non-Friend Functions

class WebBrowser { public: void clearCache(); void clearHistory(); void removeCookies(); };

// BAD: Adding "convenience" member functions class WebBrowser { // ... void clearEverything() { // Increases coupling, decreases encapsulation clearCache(); clearHistory(); removeCookies(); } };

// GOOD: Non-member function in same namespace namespace WebBrowserStuff { class WebBrowser { /* ... */ };

void clearBrowser(WebBrowser& browser) {
    browser.clearCache();
    browser.clearHistory();
    browser.removeCookies();
}

} // Doesn't increase class interface, found via ADL, can be in separate header

Item 31: Minimize Compilation Dependencies

// BAD: Heavy includes in header // widget.h #include <string> #include <vector> #include <memory> #include "gadget.h" #include "person.h"

class Widget { std::string name_; std::vector<Gadget> gadgets_; Person owner_; // ... };

// GOOD: Pimpl idiom for compilation firewall // widget.h #include <memory>

class Widget { public: Widget(); ~Widget(); // ... interface ... private: struct Impl; std::unique_ptr<Impl> pImpl_; };

// widget.cpp #include "widget.h" #include <string> #include <vector> #include "gadget.h" #include "person.h"

struct Widget::Impl { std::string name; std::vector<Gadget> gadgets; Person owner; };

Widget::Widget() : pImpl_(std::make_unique<Impl>()) {} Widget::~Widget() = default; // Must be in .cpp where Impl is complete

Mental Model

Meyers approaches C++ as a collection of gotchas that can be systematically avoided. For each situation, ask:

  • What does C++ do by default here?

  • What could go wrong?

  • How do I make the right choice obvious?

  • How do I make wrong choices fail to compile?

The "Effective" Method

When writing code:

  • Know your defaults (what does the compiler generate?)

  • Understand your types (value semantics vs reference semantics)

  • Design for correctness first, then optimize

  • Make invariants checkable at compile time when possible

Additional Resources

  • For references (books, talks), see references.md

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

renaissance-statistical-arbitrage

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

google-material-design

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

aqr-factor-investing

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

minervini-swing-trading

No summary provided by upstream source.

Repository SourceNeeds Review