Agent Skills: C++ Library Development

C++-specific library development patterns. Use when creating C++ libraries, designing header-only vs compiled libraries, configuring CMake for library targets, managing ABI stability and versioning, integrating with Conan/vcpkg, documenting with Doxygen, or testing with GoogleTest/Catch2. Extends meta-library-dev with C++ tooling and idioms.

UncategorizedID: arustydev/ai/lang-cpp-library-dev

Repository

aRustyDevLicense: AGPL-3.0
72

Install this agent skill to your local

pnpm dlx add-skill https://github.com/aRustyDev/agents/tree/HEAD/content/skills/lang-cpp-library-dev

Skill Files

Browse the full folder contents for lang-cpp-library-dev.

Download Skill

Loading file tree…

content/skills/lang-cpp-library-dev/SKILL.md

Skill Metadata

Name
lang-cpp-library-dev
Description
C++-specific library development patterns. Use when creating C++ libraries, designing header-only vs compiled libraries, configuring CMake for library targets, managing ABI stability and versioning, integrating with Conan/vcpkg, documenting with Doxygen, or testing with GoogleTest/Catch2. Extends meta-library-dev with C++ tooling and idioms.

C++ Library Development

C++-specific patterns for library development. This skill extends meta-library-dev with C++ tooling, modern C++ idioms (C++17/20/23), and ecosystem practices.

This Skill Extends

  • meta-library-dev - Foundational library patterns (API design, versioning, testing strategies)
  • lang-cpp-dev - Core C++ language features and patterns

For general concepts like semantic versioning, module organization principles, and testing pyramids, see the meta-skill first.

This Skill Adds

  • Library architecture: Header-only vs compiled libraries, template libraries
  • CMake tooling: Library targets, installation, package configuration
  • ABI stability: Version management, symbol visibility, compatibility
  • Package managers: Conan, vcpkg integration
  • Documentation: Doxygen patterns for libraries
  • Testing: GoogleTest, Catch2 patterns for library testing

This Skill Does NOT Cover

  • General library patterns - see meta-library-dev
  • Core C++ syntax and features - see lang-cpp-dev
  • CMake basics - see lang-cpp-cmake-dev
  • Memory optimization - see lang-cpp-memory-eng
  • Performance profiling - see lang-cpp-profiling-eng

Quick Reference

| Task | Command/Pattern | |------|-----------------| | CMake library target | add_library(mylib src/mylib.cpp) | | Header-only library | add_library(mylib INTERFACE) | | Build library | cmake --build build | | Install library | cmake --install build | | Run tests | ctest --test-dir build | | Generate docs | doxygen Doxyfile | | Conan install | conan install . --build=missing | | vcpkg install | vcpkg install mylib |


Library Architecture

Header-Only vs Compiled Libraries

Header-Only Libraries:

// my_library.hpp
#ifndef MY_LIBRARY_HPP
#define MY_LIBRARY_HPP

#include <string>
#include <vector>

namespace mylib {

// All code in headers - no .cpp files
template<typename T>
class Container {
public:
    void add(const T& item) {
        items_.push_back(item);
    }

    size_t size() const {
        return items_.size();
    }

private:
    std::vector<T> items_;
};

// Non-template functions must be inline
inline std::string version() {
    return "1.0.0";
}

} // namespace mylib

#endif

Compiled Libraries:

// include/mylib/mylib.hpp
#ifndef MYLIB_HPP
#define MYLIB_HPP

#include <string>
#include <memory>

namespace mylib {

class Parser {
public:
    Parser();
    ~Parser();

    // Public interface only
    bool parse(const std::string& input);
    std::string result() const;

private:
    struct Impl;  // PIMPL pattern
    std::unique_ptr<Impl> impl_;
};

} // namespace mylib

#endif

// src/mylib.cpp
#include "mylib/mylib.hpp"

namespace mylib {

struct Parser::Impl {
    std::string result;
    // Implementation details hidden
};

Parser::Parser() : impl_(std::make_unique<Impl>()) {}
Parser::~Parser() = default;

bool Parser::parse(const std::string& input) {
    // Implementation
    impl_->result = "parsed: " + input;
    return true;
}

std::string Parser::result() const {
    return impl_->result;
}

} // namespace mylib

When to Use Each

| Pattern | Use When | Pros | Cons | |---------|----------|------|------| | Header-only | Templates, small utilities | No linking, easy distribution | Longer compile times, code bloat | | Compiled | Large implementations, ABI stability | Fast compilation, smaller binaries | Requires linking, distribution complexity | | Hybrid | Mix of both | Best of both worlds | More complex build setup |


CMake Library Configuration

Basic Library Target

cmake_minimum_required(VERSION 3.15)
project(MyLibrary VERSION 1.0.0 LANGUAGES CXX)

# Set C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Compiled library
add_library(mylib
    src/parser.cpp
    src/serializer.cpp
)

# Include directories
target_include_directories(mylib
    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:include>
    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/src
)

# Link dependencies
target_link_libraries(mylib
    PUBLIC
        fmt::fmt
    PRIVATE
        nlohmann_json::nlohmann_json
)

# Set library properties
set_target_properties(mylib PROPERTIES
    VERSION ${PROJECT_VERSION}
    SOVERSION ${PROJECT_VERSION_MAJOR}
    PUBLIC_HEADER include/mylib/mylib.hpp
)

Header-Only Library

# Interface library (header-only)
add_library(mylib INTERFACE)

target_include_directories(mylib
    INTERFACE
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:include>
)

target_compile_features(mylib INTERFACE cxx_std_17)

# Header-only dependencies
target_link_libraries(mylib
    INTERFACE
        range-v3::range-v3
)

Static vs Shared Library

# Option for library type
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)

add_library(mylib
    src/parser.cpp
    src/serializer.cpp
)

# Or explicitly
add_library(mylib_static STATIC src/parser.cpp)
add_library(mylib_shared SHARED src/parser.cpp)

# Symbol visibility for shared libraries
include(GenerateExportHeader)
generate_export_header(mylib
    EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/include/mylib/export.hpp
)

target_compile_definitions(mylib
    PRIVATE
        MYLIB_EXPORTS  # When building the library
)

Installation Configuration

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

# Install targets
install(TARGETS mylib
    EXPORT mylibTargets
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mylib
)

# Install headers
install(DIRECTORY include/
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

# Export targets
install(EXPORT mylibTargets
    FILE mylibTargets.cmake
    NAMESPACE mylib::
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mylib
)

# Generate package config
configure_package_config_file(
    ${CMAKE_CURRENT_SOURCE_DIR}/cmake/mylibConfig.cmake.in
    ${CMAKE_CURRENT_BINARY_DIR}/mylibConfig.cmake
    INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mylib
)

# Generate version file
write_basic_package_version_file(
    ${CMAKE_CURRENT_BINARY_DIR}/mylibConfigVersion.cmake
    VERSION ${PROJECT_VERSION}
    COMPATIBILITY SameMajorVersion
)

# Install package config files
install(FILES
    ${CMAKE_CURRENT_BINARY_DIR}/mylibConfig.cmake
    ${CMAKE_CURRENT_BINARY_DIR}/mylibConfigVersion.cmake
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mylib
)

Package Config Template

# cmake/mylibConfig.cmake.in
@PACKAGE_INIT@

include(CMakeFindDependencyMacro)

# Find dependencies
find_dependency(fmt)

# Include targets
include("${CMAKE_CURRENT_LIST_DIR}/mylibTargets.cmake")

check_required_components(mylib)

Symbol Visibility and ABI Stability

Export Macros

// include/mylib/export.hpp
#ifndef MYLIB_EXPORT_HPP
#define MYLIB_EXPORT_HPP

#ifdef _WIN32
    #ifdef MYLIB_EXPORTS
        #define MYLIB_API __declspec(dllexport)
    #else
        #define MYLIB_API __declspec(dllimport)
    #endif
#else
    #define MYLIB_API __attribute__((visibility("default")))
#endif

#endif

// Usage in headers
#include "mylib/export.hpp"

namespace mylib {

class MYLIB_API Parser {
public:
    Parser();
    ~Parser();
    bool parse(const std::string& input);
};

} // namespace mylib

CMake Visibility Configuration

# Set default symbol visibility to hidden
set_target_properties(mylib PROPERTIES
    CXX_VISIBILITY_PRESET hidden
    VISIBILITY_INLINES_HIDDEN ON
)

# Generate export header
include(GenerateExportHeader)
generate_export_header(mylib
    BASE_NAME MYLIB
    EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/include/mylib/export.hpp
)

ABI Versioning

// Use inline namespaces for ABI versioning
namespace mylib {
inline namespace v1 {

class Parser {
    // v1 implementation
};

} // namespace v1

// When breaking ABI in next major version:
// inline namespace v2 {
//     class Parser { /* new implementation */ };
// }

} // namespace mylib

// Users automatically get latest inline namespace
mylib::Parser p;  // Uses mylib::v1::Parser

PIMPL Pattern for ABI Stability

// Public header - ABI stable
// include/mylib/database.hpp
#ifndef MYLIB_DATABASE_HPP
#define MYLIB_DATABASE_HPP

#include <memory>
#include <string>

namespace mylib {

class Database {
public:
    Database(const std::string& path);
    ~Database();

    // Copyable/movable
    Database(const Database&);
    Database& operator=(const Database&);
    Database(Database&&) noexcept;
    Database& operator=(Database&&) noexcept;

    void execute(const std::string& query);

private:
    struct Impl;
    std::unique_ptr<Impl> impl_;
};

} // namespace mylib

#endif

// Implementation - can change without breaking ABI
// src/database.cpp
#include "mylib/database.hpp"
#include <vector>
#include <map>

namespace mylib {

struct Database::Impl {
    std::string path;
    std::vector<std::string> cache;
    std::map<std::string, int> indices;

    // Private implementation details
};

Database::Database(const std::string& path)
    : impl_(std::make_unique<Impl>()) {
    impl_->path = path;
}

Database::~Database() = default;

Database::Database(const Database& other)
    : impl_(std::make_unique<Impl>(*other.impl_)) {}

Database& Database::operator=(const Database& other) {
    if (this != &other) {
        impl_ = std::make_unique<Impl>(*other.impl_);
    }
    return *this;
}

Database::Database(Database&&) noexcept = default;
Database& Database::operator=(Database&&) noexcept = default;

void Database::execute(const std::string& query) {
    // Implementation
}

} // namespace mylib

Template Library Patterns

Header Organization

include/
└── mylib/
    ├── mylib.hpp           # Main public header
    ├── container.hpp       # Template class
    └── detail/
        └── impl.hpp        # Implementation details

// include/mylib/container.hpp
#ifndef MYLIB_CONTAINER_HPP
#define MYLIB_CONTAINER_HPP

#include <vector>
#include <algorithm>

namespace mylib {

template<typename T>
class Container {
public:
    void add(const T& item);
    void add(T&& item);

    template<typename Predicate>
    void remove_if(Predicate pred);

    size_t size() const { return items_.size(); }

private:
    std::vector<T> items_;
};

// Template implementations in same header
template<typename T>
void Container<T>::add(const T& item) {
    items_.push_back(item);
}

template<typename T>
void Container<T>::add(T&& item) {
    items_.push_back(std::move(item));
}

template<typename T>
template<typename Predicate>
void Container<T>::remove_if(Predicate pred) {
    items_.erase(
        std::remove_if(items_.begin(), items_.end(), pred),
        items_.end()
    );
}

} // namespace mylib

#endif

Extern Templates (Reduce Compile Time)

// mylib.hpp - Declaration
template<typename T>
class Container {
    void add(const T& item);
};

// mylib_extern.hpp - Extern template declarations
extern template class Container<int>;
extern template class Container<std::string>;

// mylib.cpp - Explicit instantiation
#include "mylib.hpp"

template class Container<int>;
template class Container<std::string>;

Concepts for Template Constraints (C++20)

#include <concepts>

namespace mylib {

// Define concepts
template<typename T>
concept Serializable = requires(T t) {
    { t.serialize() } -> std::convertible_to<std::string>;
};

template<typename T>
concept Numeric = std::is_arithmetic_v<T>;

// Use in templates
template<Serializable T>
class DataStore {
public:
    void save(const T& data) {
        std::string serialized = data.serialize();
        // Save serialized data
    }
};

// Multiple constraints
template<typename T>
concept Container = requires(T t) {
    typename T::value_type;
    { t.size() } -> std::convertible_to<size_t>;
    { t.begin() } -> std::input_iterator;
    { t.end() } -> std::input_iterator;
};

template<Container C>
void process(const C& container) {
    for (const auto& item : container) {
        // Process item
    }
}

} // namespace mylib

Package Manager Integration

Conan Configuration

# conanfile.py
from conan import ConanFile
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout

class MyLibConan(ConanFile):
    name = "mylib"
    version = "1.0.0"
    license = "MIT"
    author = "Your Name <your.email@example.com>"
    url = "https://github.com/username/mylib"
    description = "A C++ library for parsing"
    topics = ("parsing", "cpp", "library")
    settings = "os", "compiler", "build_type", "arch"
    options = {
        "shared": [True, False],
        "fPIC": [True, False]
    }
    default_options = {
        "shared": False,
        "fPIC": True
    }
    exports_sources = "CMakeLists.txt", "src/*", "include/*"

    def requirements(self):
        self.requires("fmt/9.1.0")
        self.requires("nlohmann_json/3.11.2")

    def config_options(self):
        if self.settings.os == "Windows":
            del self.options.fPIC

    def layout(self):
        cmake_layout(self)

    def generate(self):
        tc = CMakeToolchain(self)
        tc.generate()

    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()

    def package(self):
        cmake = CMake(self)
        cmake.install()

    def package_info(self):
        self.cpp_info.libs = ["mylib"]
        self.cpp_info.includedirs = ["include"]

vcpkg Configuration

{
  "name": "mylib",
  "version": "1.0.0",
  "description": "A C++ library for parsing",
  "homepage": "https://github.com/username/mylib",
  "license": "MIT",
  "dependencies": [
    "fmt",
    "nlohmann-json"
  ],
  "features": {
    "tests": {
      "description": "Build tests",
      "dependencies": [
        "gtest"
      ]
    }
  }
}
# ports/mylib/portfile.cmake
vcpkg_from_github(
    OUT_SOURCE_PATH SOURCE_PATH
    REPO username/mylib
    REF v1.0.0
    SHA512 <hash>
    HEAD_REF main
)

vcpkg_cmake_configure(
    SOURCE_PATH "${SOURCE_PATH}"
    OPTIONS
        -DBUILD_TESTING=OFF
)

vcpkg_cmake_install()
vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/mylib)

file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
file(INSTALL "${SOURCE_PATH}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)

Documentation with Doxygen

Doxyfile Configuration

# Doxyfile
PROJECT_NAME           = "MyLib"
PROJECT_BRIEF          = "A modern C++ parsing library"
PROJECT_VERSION        = 1.0.0

INPUT                  = include/ src/ README.md
FILE_PATTERNS          = *.hpp *.cpp *.md
RECURSIVE              = YES
EXCLUDE_PATTERNS       = */detail/* */test/*

EXTRACT_ALL            = YES
EXTRACT_PRIVATE        = NO
EXTRACT_STATIC         = YES

GENERATE_HTML          = YES
HTML_OUTPUT            = docs/html
GENERATE_LATEX         = NO

USE_MDFILE_AS_MAINPAGE = README.md
MARKDOWN_SUPPORT       = YES

ENABLE_PREPROCESSING   = YES
MACRO_EXPANSION        = YES
EXPAND_ONLY_PREDEF     = NO

HAVE_DOT               = YES
CALL_GRAPH             = YES
CALLER_GRAPH           = YES
CLASS_DIAGRAMS         = YES

Documentation Comments

/**
 * @file parser.hpp
 * @brief Main parser interface
 * @author Your Name
 * @version 1.0.0
 */

#ifndef MYLIB_PARSER_HPP
#define MYLIB_PARSER_HPP

namespace mylib {

/**
 * @brief A parser for processing input data
 *
 * This class provides methods for parsing various input formats
 * and converting them to structured data.
 *
 * @code
 * Parser p;
 * p.parse("input data");
 * auto result = p.result();
 * @endcode
 *
 * @note The parser is not thread-safe
 * @warning Reusing the same parser instance may lead to data races
 */
class Parser {
public:
    /**
     * @brief Construct a new Parser object
     *
     * @param strict Enable strict parsing mode
     * @throw std::invalid_argument if configuration is invalid
     */
    explicit Parser(bool strict = false);

    /**
     * @brief Parse input data
     *
     * @param input The input string to parse
     * @return true if parsing succeeded
     * @return false if parsing failed
     *
     * @pre input must not be empty
     * @post result() contains parsed data if successful
     *
     * @see result()
     */
    bool parse(const std::string& input);

    /**
     * @brief Get the parsing result
     *
     * @return const std::string& Reference to the result
     *
     * @pre parse() must have been called successfully
     */
    const std::string& result() const;

private:
    bool strict_;         ///< Strict parsing mode flag
    std::string result_;  ///< Parsed result storage
};

/**
 * @brief Parse input with default settings
 *
 * @tparam T The output type
 * @param input Input string
 * @return T Parsed result
 *
 * @example
 * @code
 * auto data = parse<Data>("input");
 * @endcode
 */
template<typename T>
T parse(const std::string& input);

} // namespace mylib

#endif

CMake Integration

# Find Doxygen
find_package(Doxygen)

if(DOXYGEN_FOUND)
    # Configure Doxyfile
    set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in)
    set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)

    configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)

    # Add documentation target
    add_custom_target(docs
        COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
        COMMENT "Generating API documentation with Doxygen"
        VERBATIM
    )
endif()

Testing with GoogleTest

CMake Test Configuration

# Enable testing
enable_testing()

# Find GoogleTest
find_package(GTest REQUIRED)

# Test executable
add_executable(mylib_test
    tests/parser_test.cpp
    tests/serializer_test.cpp
)

target_link_libraries(mylib_test
    PRIVATE
        mylib
        GTest::gtest
        GTest::gtest_main
)

# Discover tests
include(GoogleTest)
gtest_discover_tests(mylib_test)

Test Structure

// tests/parser_test.cpp
#include <gtest/gtest.h>
#include "mylib/parser.hpp"

namespace mylib {
namespace test {

class ParserTest : public ::testing::Test {
protected:
    void SetUp() override {
        parser = std::make_unique<Parser>();
    }

    void TearDown() override {
        parser.reset();
    }

    std::unique_ptr<Parser> parser;
};

TEST_F(ParserTest, ParseValidInput) {
    ASSERT_TRUE(parser->parse("valid input"));
    EXPECT_EQ(parser->result(), "parsed: valid input");
}

TEST_F(ParserTest, ParseEmptyInput) {
    EXPECT_FALSE(parser->parse(""));
}

TEST_F(ParserTest, ParseWithStrictMode) {
    Parser strict_parser(true);
    EXPECT_THROW(strict_parser.parse("invalid"), std::runtime_error);
}

// Parameterized tests
class ParserParamTest : public ::testing::TestWithParam<std::string> {};

TEST_P(ParserParamTest, ParseMultipleInputs) {
    Parser p;
    EXPECT_TRUE(p.parse(GetParam()));
}

INSTANTIATE_TEST_SUITE_P(
    ValidInputs,
    ParserParamTest,
    ::testing::Values("input1", "input2", "input3")
);

} // namespace test
} // namespace mylib

Testing with Catch2

CMake Configuration

find_package(Catch2 3 REQUIRED)

add_executable(mylib_test
    tests/parser_test.cpp
)

target_link_libraries(mylib_test
    PRIVATE
        mylib
        Catch2::Catch2WithMain
)

include(Catch)
catch_discover_tests(mylib_test)

Test Structure

// tests/parser_test.cpp
#include <catch2/catch_test_macros.hpp>
#include "mylib/parser.hpp"

TEST_CASE("Parser handles valid input", "[parser]") {
    mylib::Parser p;

    SECTION("Basic parsing") {
        REQUIRE(p.parse("test input"));
        REQUIRE(p.result() == "parsed: test input");
    }

    SECTION("Empty input fails") {
        REQUIRE_FALSE(p.parse(""));
    }
}

TEST_CASE("Parser with strict mode", "[parser][strict]") {
    mylib::Parser p(true);

    REQUIRE_THROWS_AS(p.parse("invalid"), std::runtime_error);
}

// Template tests
TEMPLATE_TEST_CASE("Container works with different types",
                   "[container][template]",
                   int, double, std::string) {
    mylib::Container<TestType> container;

    TestType value{};
    container.add(value);

    REQUIRE(container.size() == 1);
}

Versioning Best Practices

Semantic Versioning

MAJOR.MINOR.PATCH (e.g., 1.2.3)

MAJOR: Incompatible API changes (breaking changes)
MINOR: Backward-compatible functionality additions
PATCH: Backward-compatible bug fixes

Version Header

// include/mylib/version.hpp
#ifndef MYLIB_VERSION_HPP
#define MYLIB_VERSION_HPP

#define MYLIB_VERSION_MAJOR 1
#define MYLIB_VERSION_MINOR 0
#define MYLIB_VERSION_PATCH 0

#define MYLIB_VERSION \
    (MYLIB_VERSION_MAJOR * 10000 + \
     MYLIB_VERSION_MINOR * 100 + \
     MYLIB_VERSION_PATCH)

#define MYLIB_VERSION_STRING "1.0.0"

namespace mylib {

struct Version {
    static constexpr int major = MYLIB_VERSION_MAJOR;
    static constexpr int minor = MYLIB_VERSION_MINOR;
    static constexpr int patch = MYLIB_VERSION_PATCH;
    static constexpr const char* string = MYLIB_VERSION_STRING;
};

} // namespace mylib

#endif

CMake Version Configuration

# CMakeLists.txt
project(MyLib VERSION 1.0.0)

# Generate version header
configure_file(
    ${CMAKE_CURRENT_SOURCE_DIR}/include/mylib/version.hpp.in
    ${CMAKE_CURRENT_BINARY_DIR}/include/mylib/version.hpp
)
// include/mylib/version.hpp.in
#ifndef MYLIB_VERSION_HPP
#define MYLIB_VERSION_HPP

#define MYLIB_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define MYLIB_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define MYLIB_VERSION_PATCH @PROJECT_VERSION_PATCH@

#define MYLIB_VERSION_STRING "@PROJECT_VERSION@"

#endif

Example: Complete Library Structure

mylib/
├── CMakeLists.txt
├── conanfile.py
├── vcpkg.json
├── README.md
├── LICENSE
├── CHANGELOG.md
├── Doxyfile
├── .clang-format
├── include/
│   └── mylib/
│       ├── mylib.hpp          # Main public header
│       ├── parser.hpp
│       ├── serializer.hpp
│       ├── version.hpp
│       └── export.hpp
├── src/
│   ├── parser.cpp
│   └── serializer.cpp
├── tests/
│   ├── CMakeLists.txt
│   ├── parser_test.cpp
│   └── serializer_test.cpp
├── examples/
│   ├── CMakeLists.txt
│   ├── basic_usage.cpp
│   └── advanced_usage.cpp
├── docs/
│   └── Doxyfile.in
└── cmake/
    ├── mylibConfig.cmake.in
    └── FindMyLibDeps.cmake

Anti-Patterns

1. Exposing Implementation Details

// Bad: Exposing internal types
class Parser {
public:
    std::shared_ptr<InternalNode> parse(const std::string& input);
};

// Good: Return opaque type or public interface
class Parser {
public:
    Document parse(const std::string& input);
};

2. Using using namespace in Headers

// Bad: Pollutes namespace for users
// mylib.hpp
using namespace std;

class Parser {
    string parse(const string& input);
};

// Good: Fully qualified names
// mylib.hpp
class Parser {
    std::string parse(const std::string& input);
};

3. Inline Everything

// Bad: Large inline functions
class Parser {
    void parse(const std::string& input) {
        // 100 lines of code...
    }
};

// Good: Separate declaration and definition
class Parser {
    void parse(const std::string& input);
};

4. Breaking ABI Without Major Version Bump

// v1.0.0
class Data {
    int value;
};

// v1.1.0 - WRONG! This breaks ABI
class Data {
    int value;
    int newValue;  // Changes size/layout
};

// Correct: Create new type or bump major version

References