C++20 - The Complete Guide
$22.90
Minimum price
$44.90
Suggested price

C++20 - The Complete Guide

About the Book

C++20 is the next evolution in modern C++ programming, which will be supported step-by-step by the latest version of gcc, clang, and Visual C++.

C++20 is a big step, maybe even larger than C++11.

It contains a couple of new key features (modules, concepts, ranges, corountines) plus several small but valuable language and library features, which will change the way we program in C++. As usual, not everything is self-explanatory, combining new features gives even more power, and there are hidden traps.

This book presents all the new language and library features of C++20. It covers the motivation and context of each new feature with examples and background information. The focus is on how these features impact day-to-day programming, what it means to combine them, and how to benefit from C++20 in practice.

Buy early, pay less, free updates

Note that this book is published step-by-step. The first public version was published in June 2021. Since then, the contents grows with new chapters, examples, and caveats about the features of C++20 and I integrate all feedback I get for the pages already published.

The book is feature omplete now.

Just minore details and copy editing is missing.

See cppstd20.com for a detailed list of all the topics covered.

As written, once you bought it you will get all updates for free.

PDF versus Other Formats

I write the book in LaTeX and generate PDF from it (the way I wrote my other books). The other formats (epub, mobi, and online reading) come from the leanpub markdown interface, for which I generate the necessary input from LaTeX by script.

Thus, the PDF layout has a better quality than the other formats. For example, the syntax highlighting rules for the formats other than PDF have to get fixed as soon as possible and the index is missing yet. Leanpub and me are working on corresponding improvements.

I hope you enjoy and benefit.

Nico

#cpp20tcg

About the Author

Nicolai M. Josuttis
Nicolai M. Josuttis

Nicolai Josuttis (http://www.josuttis.com) is well known in the programming community because he not only speaks and writes with authority, being the (co-)author of the world-wide best sellers

but is also an innovative presenter, having talked at various conferences and events.

He is an independent trainer and speaker being active in C++ standardization for more than 20 years.

Nicolai M. Josuttis

Episode 89

Table of Contents

  • Preface
    • An Experiment
    • Versions of This Book
    • Acknowledgments
  • About This Book
    • What You Should Know Before Reading This Book
    • Overall Structure of the Book
    • How to Read This Book
    • The Way I Implement
      • Initializations
      • Error Terminology
      • Code Simplifications
    • The C++ Standards
    • Example Code and Additional Information
    • Feedback
  • 1. Comparisons and Operator <=>
    • 1.1 Motivation for Operator<=>
      • 1.1.1 Defining Comparison Operators Before C++20
      • 1.1.2 Defining Comparison Operators Since C++20
    • 1.2 Defining and Using Comparisons
      • 1.2.1 Using Operator<=>
      • 1.2.2 Comparison Category Types
      • 1.2.3 Using Comparison Categories with operator<=>
      • 1.2.4 Calling operator<=>
      • 1.2.5 Dealing with Multiple Ordering Criteria
    • 1.3 Defining operator<=> and operator==
      • 1.3.1 Defaulted operator== and operator<=>
      • 1.3.2 Defaulted operator<=> Implies Defaulted operator==
      • 1.3.3 Implementation of the Defaulted operator<=>
    • 1.4 Overload Resolution with Rewritten Expressions
    • 1.5 Using Operator operator <=> in Generic Code
      • 1.5.1 compare_three_way
      • 1.5.2 Algorithm lexicographical_compare_three_way()
    • 1.6 Compatibility Issues with the Comparison Operators
      • 1.6.1 Delegating Free-Standing Operator
      • 1.6.2 Inheritance with Protected Members
    • 1.7 Afternotes
  • 2. Placeholder Types for Function Parameters
    • 2.1 auto for Parameters of Ordinary Functions
      • 2.1.1 auto for Parameters of Member Functions
    • 2.2 Using auto for Parameters in Practice
      • 2.2.1 Deferred Type Checks with auto
      • 2.2.2 auto Functions versus Lambdas
    • 2.3 auto for Parameters in Detail
      • 2.3.1 Basic Constraints for auto Parameters
      • 2.3.2 Combining Template and auto Parameters
    • 2.4 Afternotes
  • 3. Concepts and Requirements
    • 3.1 Motivating Example of Concepts and Requirements
      • 3.1.1 Improving the Template Step-by-Step
      • 3.1.2 The Whole Resulting Program
    • 3.2 Typical Application of Concepts and Requirements in Practice
      • 3.2.1 Requirements to Understand Code and Error Messages
      • 3.2.2 Requirements to Disable Generic Code
      • 3.2.3 Requirements to Use Different Statements
      • 3.2.4 The Example as a Whole
      • 3.2.5 Former Workarounds
    • 3.3 Constraints and Requirements in Detail
      • 3.3.1 Constraints
      • 3.3.2 Ad hoc Boolean Expressions
      • 3.3.3 requires Expressions
    • 3.4 Concepts in Detail
      • 3.4.1 Defining Concepts
      • 3.4.2 Special Abilities of Concepts
      • 3.4.3 Using Concepts as Type Constraints
    • 3.5 Subsuming Constraints and Concepts
      • 3.5.1 Indirect Subsumptions
    • 3.6 Semantic Constraints
    • 3.7 Design Guidelines for Concepts
      • 3.7.1 Dealing with Multiple Requirements
      • 3.7.2 Concepts versus Traits and Expressions
      • 3.7.3 When to Use if constexpr
    • 3.8 Other Stuff of Concepts
    • 3.9 Afternotes
  • 4. Standard Concepts in Detail
    • 4.1 Overview of all Standard Concepts
      • 4.1.1 Header Files and Namespaces
      • 4.1.2 Standard Concepts Subsume
    • 4.2 Language-Related Concepts
      • 4.2.1 Arithmetic Concepts
      • 4.2.2 Object Concepts
      • 4.2.3 Concepts for Relations between Types
      • 4.2.4 Comparison Concepts
    • 4.3 Concepts for Iterators and Ranges
      • 4.3.1 Concepts for Ranges and Views
      • 4.3.2 Concepts for Pointers-Like Objects
      • 4.3.3 Concepts for Iterators
      • 4.3.4 Iterator Concepts for Algorithms
    • 4.4 Concepts for Callables
      • 4.4.1 Basic Concepts for Callables
      • 4.4.2 Concepts for Callables Used by Iterators
    • 4.5 Auxiliary Concepts
      • 4.5.1 Concepts for Specific Type Attributes
      • 4.5.2 Concepts for Incrementable Types
    • 4.6 Open
    • 4.7 Afternotes
  • 5. Ranges and Views
    • 5.1 A Tour of Ranges by Example
      • 5.1.1 Passing Containers to Algorithms as Ranges
      • 5.1.2 Constraints and Utilities for Ranges
      • 5.1.3 Views
      • 5.1.4 Sentinels
      • 5.1.5 Range Definitions with Sentinels and Counts
      • 5.1.6 Projections
      • 5.1.7 Utilities to Implement Code for Ranges
      • 5.1.8 Limitations and Drawbacks of Ranges
    • 5.2 Using Views
      • 5.2.1 Views on Ranges
      • 5.2.2 Pipelines for Temporary Ranges
      • 5.2.3 Lazy Evaluation
      • 5.2.4 Performance Issues with Filters
      • 5.2.5 Views and Pipelines with Write Access
      • 5.2.6 Write Access with Filter Views
    • 5.3 Borrowed Iterators and Ranges
      • 5.3.1 Borrowed Iterators
      • 5.3.2 Borrowed Ranges
    • 5.4 Ranges and const
      • 5.4.1 Views Remove the Propagation of const
      • 5.4.2 Bringing Back Deep Constness to Views
      • 5.4.3 Generic Code Should Take Ranges with Non-const &&
    • 5.5 Open
    • 5.6 Afternotes
  • 6. Utilities for Ranges and Views
    • 6.1 Major Range Adaptors
      • 6.1.1 Range Adaptor all()
      • 6.1.2 Range Adaptor counted()
      • 6.1.3 Range Adaptor common()
    • 6.2 New Iterators
      • 6.2.1 std::counted_iterator
      • 6.2.2 std::common_iterator
      • 6.2.3 std::default_sentinel
      • 6.2.4 std::unreachable_sentinel
    • 6.3 New Functions and Type Functions in std::ranges
      • 6.3.1 Auxiliary Value Functions
      • 6.3.2 Auxiliary Type Functions
    • 6.4 Algorithm Overview
    • 6.5 Open
    • 6.6 Afternotes
  • 7. View Types in Detail
    • 7.1 Overview of all Views
      • 7.1.1 Overview of Source Views
      • 7.1.2 Overview of Adapting Views
    • 7.2 Base Classes for Views
    • 7.3 Source Views to External Elements
      • 7.3.1 Subrange
      • 7.3.2 Ref View
      • 7.3.3 Owning View
      • 7.3.4 Common View
    • 7.4 Generating Views
      • 7.4.1 Iota View
      • 7.4.2 Single View
      • 7.4.3 Empty View
      • 7.4.4 IStream View
      • 7.4.5 String View
      • 7.4.6 Span
    • 7.5 Filtering Views
      • 7.5.1 Take View
      • 7.5.2 Take-While View
      • 7.5.3 Drop View
      • 7.5.4 Drop-While View
      • 7.5.5 Filter View
    • 7.6 Transforming Views
      • 7.6.1 Transform View
      • 7.6.2 Elements View
      • 7.6.3 Keys View
      • 7.6.4 Values View
    • 7.7 Mutating Views
      • 7.7.1 Reverse View
    • 7.8 Views for Multiple Ranges
      • 7.8.1 Split and Lazy-Split View
      • 7.8.2 Join View
    • 7.9 Open
    • 7.10 Afternotes
  • 8. Spans
    • 8.1 Using Spans
      • 8.1.1 Fixed and Dynamic Extent
      • 8.1.2 Example Using a Span with Fixed Extent
      • 8.1.3 Example Using a Span with a Dynamic Extent
    • 8.2 Spans Considered Harmful
    • 8.3 Design Aspects of Spans
      • 8.3.1 Performance of Spans
      • 8.3.2 const Correctness of Spans
      • 8.3.3 Using Spans as Parameters in Generic Code
    • 8.4 Span Operations
      • 8.4.1 Span Operations and Member Types Overview
    • 8.5 Afternotes
  • 9. Formatted Output
    • 9.1 Formatted Output by Example
      • 9.1.1 Using std::format()
      • 9.1.2 Using std::format_to_n()
      • 9.1.3 Using std::format_to()
      • 9.1.4 Using std::formatted_size()
    • 9.2 Performance of the Formatting Library
      • 9.2.1 Using std::vformat() and vformat_to()
    • 9.3 Formatted Output in Detail
      • 9.3.1 General Format of Format Strings
      • 9.3.2 Standard Format Specifiers
      • 9.3.3 Width, Precision, and Fill Characters
      • 9.3.4 Format/Type Specifiers
    • 9.4 Internationalization
    • 9.5 Error Handling
    • 9.6 User-Defined Formatted Output
      • 9.6.1 Basic Formatter API
      • 9.6.2 Improved Parsing
      • 9.6.3 Using Standard Formatters for User-Defined Formatters
      • 9.6.4 Using Standard Formatters for Strings
    • 9.7 Afternotes
  • 10. Dates and Time Zones for <chrono>
    • 10.1 Overview by Example
      • 10.1.1 Schedule a Meeting on the 5th of Every Month
      • 10.1.2 Schedule a Meeting Every First Monday
    • 10.2 Basic Chrono Concepts and Terminology
    • 10.3 Basic Chrono Extensions with C++20
      • 10.3.1 Duration Types
      • 10.3.2 Clocks
      • 10.3.3 Timepoint Types
      • 10.3.4 Calendrical Types
      • 10.3.5 Time Type hh_mm_ss
    • 10.4 Time Zones
      • 10.4.1 Characteristics of Time Zones
      • 10.4.2 Using Time Zones
    • 10.5 I/O with Chrono Types
      • 10.5.1 Default Output Formats
      • 10.5.2 Formatted Output
      • 10.5.3 Locale Dependent Output
      • 10.5.4 Formatted Input
    • 10.6 Using the Chrono Extensions in Practice
      • 10.6.1 Invalid Dates
      • 10.6.2 Dealing with months and years
      • 10.6.3 Parsing Time Points and Durations
      • 10.6.4 Dealing with Time Zone Abbreviations
      • 10.6.5 Custom Timezones
    • 10.7 Clocks in Detail
      • 10.7.1 Clocks with a Specified Epoch
      • 10.7.2 The Pseudo Clock local_t
      • 10.7.3 Dealing with Leap Seconds
      • 10.7.4 Conversions between Clocks
      • 10.7.5 Dealing with the File Clock
    • 10.8 Other New Chrono Features
    • 10.9 Afternotes
  • 11. std::jthread and Stop Tokens
    • 11.1 Motivation for std::jthread
      • 11.1.1 The Problem of std::thread
      • 11.1.2 Using std::jthread
      • 11.1.3 Stop Tokens and Stop Callbacks
      • 11.1.4 Stop Tokens and Condition Variables
    • 11.2 Stop Sources and Stop Tokens
      • 11.2.1 Stop Sources and Stop Tokens in Detail
      • 11.2.2 Using Stop Callbacks
      • 11.2.3 Constraints and Guarantees of Stop Tokens
    • 11.3 std::jthread In Detail
      • 11.3.1 Using Stop Tokens with std::jthread
    • 11.4 Afternotes
  • 12. Concurrency Features
    • 12.1 Thread Synchronization with Latches and Barriers
      • 12.1.1 Latches
      • 12.1.2 Barriers
    • 12.2 Semaphores
      • 12.2.1 Example of Using Counting Semaphores
      • 12.2.2 Example of Using Binary Semaphores
    • 12.3 Extensions Atomics
      • 12.3.1 Atomic References with std::atomic_ref<>
      • 12.3.2 Atomic Shared Pointers
      • 12.3.3 Atomic Floating-Point Types
      • 12.3.4 Thread Synchronization with Atomic Types
      • 12.3.5 Extensions for std::atomic_flag
    • 12.4 Synchronized Output Streams
      • 12.4.1 Motivation of Synchronized Output Streams
      • 12.4.2 Using of Synchronized Output Streams
      • 12.4.3 Using Synchronized Output Streams for Files
      • 12.4.4 Using Synchronized Output Streams as Output Streams
      • 12.4.5 Synchronized Output Streams in Practice
      • 12.4.6 Synchronized Output Streams in Detail
    • 12.5 Afternotes
  • 13. Coroutines
    • 13.1 What Are Coroutines?
    • 13.2 A First Coroutine Example
      • 13.2.1 Defining the Coroutine
      • 13.2.2 Using the Coroutine
      • 13.2.3 Lifetime Issues with Call-by-Reference
      • 13.2.4 Coroutines calling Coroutines
      • 13.2.5 Implementing the Coroutine Interface
      • 13.2.6 Bootstrapping Interface, Handle, and Promise
      • 13.2.7 Memory Management
    • 13.3 Coroutines That Yield or Return Values
      • 13.3.1 Using co_yield
      • 13.3.2 Using co_return
    • 13.4 Coroutine Awaitables and Awaiters
      • 13.4.1 Awaiters
      • 13.4.2 Standard Awaiters
      • 13.4.3 Resuming Sub-Coroutines
      • 13.4.4 Passing Values From Suspension Back to the Coroutine
    • 13.5 Afternotes
  • 14. Coroutines in Detail
    • 14.1 Coroutine Constraints
      • 14.1.1 Coroutine Lambdas
    • 14.2 The Coroutine Frame and the Promises
      • 14.2.1 How Coroutine Interfaces, Promises, and Awaitables Interact
    • 14.3 Coroutine Promises in Detail
      • 14.3.1 Promise Operations
    • 14.4 Coroutine Handles in Detail
      • 14.4.1 std::coroutine_handle<void>
    • 14.5 Exceptions in Coroutines
    • 14.6 Allocating Memory for the Coroutine Frame
      • 14.6.1 How Coroutines Allocate Memory
      • 14.6.2 Avoiding Heap Memory Allocation
      • 14.6.3 get_return_object_on_allocation_failure()
    • 14.7 co_await and Awaiters in Detail
      • 14.7.1 Details of the Awaiter Interface
      • 14.7.2 Let co_await Update Running Coroutines
      • 14.7.3 Symmetric Transfer with Awaiters for Continuation
    • 14.8 Other Ways to Deal with co_await
      • 14.8.1 await_transform()
      • 14.8.2 operator co_await()
    • 14.9 Concurrent Use of Coroutines
      • 14.9.1 co_await Coroutines
      • 14.9.2 A Thread Pool for Coroutine Tasks
      • 14.9.3 What C++ Libraries Will Provide After C++20
    • 14.10 Coroutine Traits
  • 15. Modules
    • 15.1 Motivation of Modules by a First Example
      • 15.1.1 Implementing and Exporting a Module
      • 15.1.2 Compiling Module Units
      • 15.1.3 Importing and Using a Module
      • 15.1.4 Reachable versus Visible
      • 15.1.5 Modules and Namespaces
    • 15.2 Modules with Multiple Files
      • 15.2.1 Module Units
      • 15.2.2 Implementation Units
      • 15.2.3 Internal Partitions
      • 15.2.4 Interface Partitions
      • 15.2.5 Summary of Splitting Modules into Different Files
    • 15.3 Dealing with Modules in Practice
      • 15.3.1 Dealing with Module Files with Different Compilers
      • 15.3.2 Dealing with Header Files
    • 15.4 Modules in Detail
      • 15.4.1 Private Module Fragments
      • 15.4.2 Module Declaration/Export in Detail
      • 15.4.3 Umbrella Modules
      • 15.4.4 Module Import in Detail
      • 15.4.5 Reachable versus Visible Symbols in Detail
    • 15.5 Afternotes
  • 16. Lambda Extensions
    • 16.1 Generic Lambdas with Template Parameters
      • 16.1.1 Using Template Parameters for Generic Lambdas in Practice
      • 16.1.2 Explicit Specification of Lambda Template Parameters
    • 16.2 Calling the Default Constructor of Lambdas
    • 16.3 Lambdas as Non-Type Template Parameters
    • 16.4 consteval Lambdas
    • 16.5 Changes for Capturing
      • 16.5.1 Capturing this and *this
      • 16.5.2 Capturing Structured Bindings
      • 16.5.3 Capturing Parameter Packs of Variadic Templates
      • 16.5.4 Lambdas as Coroutines
    • 16.6 Afternotes
  • 17. Compile-Time Computing
    • 17.1 Keyword constinit
      • 17.1.1 Using constinit in Practice
      • 17.1.2 How constinit Solves the Static Initialization Order Fiasco
    • 17.2 Keyword consteval
      • 17.2.1 A First consteval Example
      • 17.2.2 constexpr versus consteval
      • 17.2.3 Using consteval in Practice
      • 17.2.4 Compile-Time Value versus Compile-Time Context
    • 17.3 Relaxed Constraints for constexpr Functions
    • 17.4 std::is_constant_evaluated()
      • 17.4.1 std::is_constant_evaluated() in Detail
    • 17.5 Using Heap Memory, Vectors, and Strings at Compile Time
      • 17.5.1 Using Vectors at Compile Time
      • 17.5.2 Returning a Collection at Compile Time
      • 17.5.3 Using Strings at Compile Time
    • 17.6 Other constexpr Extensions
      • 17.6.1 constexpr Language Extensions
      • 17.6.2 constexpr Library Extensions
    • 17.7 Afternotes
  • 18. Non-Type Template Parameter (NTTP) Extensions
    • 18.1 New Types for Non-Type Template Parameters
      • 18.1.1 double Values as Non-Type Template Parameters
      • 18.1.2 Objects as Non-Type Template Parameters
      • 18.1.3 Lambdas as Non-Type Template Parameters
    • 18.2 Details of Floating-Point Values as NTTP’s
    • 18.3 Details of Objects as NTTP’s
    • 18.4 Afternotes
  • 19. New Type Traits
    •  
      • 19.0.1 Type Traits for Type Classification
      • 19.0.2 is_bounded_array_v<> and is_unbounded_array_v
      • 19.0.3 Type Traits for Type Inspection
      • 19.0.4 is_nothrow_convertible_v<>
      • 19.0.5 Type Traits for Type Conversion
      • 19.0.6 remove_cvref_t<>
      • 19.0.7 unwrap_reference<> and unwrap_ref_decay_t
      • 19.0.8 common_reference<>_t
      • 19.0.9 type_identity_t<>
      • 19.0.10 Type Traits for iterators
      • 19.0.11 iter_difference_t<>
      • 19.0.12 iter_value_t<>
      • 19.0.13 iter_reference_t<> and iter_rvalue_reference_t<>
    • 19.1 Type Traits for Layout Compatibility
      • 19.1.1 is_layout_compatible_v<>
      • 19.1.2 is_layout_pointer_interconvertible_base_of_v<>
    • 19.2 is_pointer_interconvertible_with_class<>() and is_corresponding_member<>()
    • 19.3 Afternotes
  • 20. Small Improvements for the Core Language
    • 20.1 Range-Based for Loop with Initialization
    • 20.2 using for Enumeration Values
    • 20.3 Delegate Enumerations Types to different Scopes
    • 20.4 New Character Type char8_t
      • 20.4.1 Changes in the C++ Standard Library for char8_t
      • 20.4.2 Broken Backward Compatibility
    • 20.5 Improvements for Aggregates
      • 20.5.1 Designated Initializers
      • 20.5.2 Aggregate Initialization with Parentheses
      • 20.5.3 Definition of Aggregates
    • 20.6 New Attributes and Attribute Features
      • 20.6.1 Attributes [[likely]] and [[unlikely]]
      • 20.6.2 Attribute [[no_unique_address]]
      • 20.6.3 Attribute [[nodiscard]] with Parameter
    • 20.7 Feature Test Macros
    • 20.8 Afternotes
  • 21. Small Improvements for Generic Programming
    • 21.1 Implicit typename for Type Members of Template Parameters
      • 21.1.1 Rules for Implicit typename in Detail
    • 21.2 Improvements for Aggregates in Generic Code
      • 21.2.1 Class Template Argument Deduction (CTAD) for Aggregates
    • 21.3 Conditional explicit
      • 21.3.1 Conditional explicit in the Standard Library
    • 21.4 Afternotes
  • 22. Small Improvements for the C++ Standard Library
    • 22.1 Updates for String Types
      • 22.1.1 String Members starts_with() and ends_with()
      • 22.1.2 Restricted String Member reserve()
    • 22.2 std::source_location
    • 22.3 Safe Comparisons of Integrals Values and Sizes
      • 22.3.1 Safe Comparisons of Integrals Values
      • 22.3.2 ssize()
    • 22.4 Mathematical Constants
    • 22.5 Utilities to Deal with Bits
      • 22.5.1 Bit Operations
      • 22.5.2 std::bit_cast<>()
      • 22.5.3 std::endian
    • 22.6 <version>
    • 22.7 Extensions for Algorithms
      • 22.7.1 Range Support
      • 22.7.2 New Algorithms
      • 22.7.3 unseq Execution Policy for Algorithms
    • 22.8 Afternotes
  • 23. Deprecated and Removed Features
    • 23.1 Deprecated and Removed Core Language Features
    • 23.2 Deprecated and Removed Library Features
      • 23.2.1 Deprecated Library Features
      • 23.2.2 Removed Library Features
    • 23.3 Afternotes
  • Glossary
    • A
      • aggregate
      • argument-dependent lookup (ADL)
    • C
      • class template argument deduction (CTAD)
    • F
      • forwarding reference
      • full specialization
      • function object (functor)
    • G
      • glvalue
    • I
      • incomplete type
    • L
      • lvalue
    • P
      • partial specialization
      • predicate
      • prvalue
    • R
      • resource acquisition is initialization (RAII)
      • regular type
      • rvalue
    • S
      • semiregular type
      • substitution failure is not an error (SFINAE)
      • small/short string optimization (SSO)
      • stateless
      • standard template library (STL)
    • U
      • universal reference
    • V
      • value category
      • variable template
      • variadic template
    • X
      • xvalue
  • Notes

The Leanpub 60-day 100% Happiness Guarantee

Within 60 days of purchase you can get a 100% refund on any Leanpub purchase, in two clicks.

See full terms

Do Well. Do Good.

Authors have earned$11,716,512writing, publishing and selling on Leanpub, earning 80% royalties while saving up to 25 million pounds of CO2 and up to 46,000 trees.

Learn more about writing on Leanpub

Free Updates. DRM Free.

If you buy a Leanpub book, you get free updates for as long as the author updates the book! Many authors use Leanpub to publish their books in-progress, while they are writing them. All readers get free updates, regardless of when they bought the book or how much they paid (including free).

Most Leanpub books are available in PDF (for computers), EPUB (for phones and tablets) and MOBI (for Kindle). The formats that a book includes are shown at the top right corner of this page.

Finally, Leanpub books don't have any DRM copy-protection nonsense, so you can easily read them on any supported device.

Learn more about Leanpub's ebook formats and where to read them

Write and Publish on Leanpub

You can use Leanpub to easily write, publish and sell in-progress and completed ebooks and online courses!

Leanpub is a powerful platform for serious authors, combining a simple, elegant writing and publishing workflow with a store focused on selling in-progress ebooks.

Leanpub is a magical typewriter for authors: just write in plain text, and to publish your ebook, just click a button. (Or, if you are producing your ebook your own way, you can even upload your own PDF, EPUB and/or MOBI files and then publish with one click!) It really is that easy.

Learn more about writing on Leanpub