This document is part of the more general Chromium C++ style guide. It summarizes the supported state of new and updated language and library features in recent C++ standards and the Abseil library. This guide applies to both Chromium and its subprojects, though subprojects can choose to be more restrictive if necessary for toolchain support.
The C++ language has in recent years received an updated standard every three years (C++11, C++14, etc.). For various reasons, Chromium does not immediately allow new features on the publication of such a standard. Instead, once Chromium supports the toolchain to a certain extent (e.g., build support is ready), a standard is declared “initially supported”, with new language/library features banned pending discussion but not yet allowed.
You can propose changing the status of a feature by sending an email to cxx@chromium.org. Include a short blurb on what the feature is and why you think it should or should not be allowed, along with links to any relevant previous discussion. If the list arrives at some consensus, send a codereview to change this file accordingly, linking to your discussion thread.
If an item remains on the TBD list two years after initial support is added, style arbiters should explicitly move it to an appropriate allowlist or blocklist, allowing it if there are no obvious reasons to ban.
The current status of existing standards and Abseil features is:
The following C++11 language features are not allowed in the Chromium codebase.
inline namespace foo { ... }
Description: Allows better versioning of namespaces.
Documentation: Inline namespaces
Notes:
long long var = value;
Description: An integer of at least 64 bits.
Documentation: Fundamental types
Notes:
<stdint.h>
type if you need a 64-bit number. Discussion threadDistanceType var = 12_km;
Description: Allows user-defined literal expressions.
Documentation: User-defined literals
Notes:
The following C++11 library features are not allowed in the Chromium codebase.
#include <cfenv> #include <fenv.h>
Description: Provides floating point status flags and control modes for C-compatible code.
Documentation: Standard library header <cfenv>
Notes:
#include <chrono>
Description: A standard date and time library.
Documentation: Date and time utilities
Notes:
base/time
. Keep using the base/time
classes.#include <exception>
Description: Exception throwing and handling.
Documentation: Standard library header <exception>
Notes:
Exceptions are banned by the Google Style Guide and disabled in Chromium compiles. However, the noexcept
specifier is explicitly allowed.
std::mt19937 generator;
Description: Methods of generating random numbers.
Documentation: Pseudo-random number generation
Notes:
Do not use any random number engines or generators from <random>
. Instead, use base::RandomBitGenerator
. (You may use the distributions from <random>
.)
#include <ratio>
Description: Provides compile-time rational numbers.
Documentation: std::ratio
Notes:
#include <regex>
Description: A standard regular expressions library.
Documentation: Regular expressions library
Notes:
third_party/re2
.auto x = std::bind(function, args, ...);
Description: Declares a function object bound to certain arguments.
Documentation: std::bind
Notes:
Use base::Bind
instead. Compared to std::bind
, base::Bind
helps prevent lifetime issues by preventing binding of capturing lambdas and by forcing callers to declare raw pointers as Unretained
.
std::function x = [] { return 10; }; std::function y = std::bind(foo, args);
Description: Wraps a standard polymorphic function.
Documentation: std::function
Notes:
Use base::{Once,Repeating}Callback
instead. Compared to std::function
, base::{Once,Repeating}Callback
directly supports Chromium's refcounting classes and weak pointers and deals with additional thread safety concerns.
std::shared_ptr<int> x = std::make_shared<int>(10);
Description: Allows shared ownership of a pointer through reference counts.
Documentation: std::shared_ptr
Notes:
Unlike base::RefCounted
, uses extrinsic rather than intrinsic reference counting. Could plausibly be used in Chromium, but would require significant migration.
int x = std::stoi("10");
Description: Converts strings to/from numbers.
Documentation: std::stoi
, std::stol
, std::stoll
, std::stoul
, std::stoull
, std::stof
, std::stod
, std::stold
, std::to_string
Notes:
base/strings/string_number_conversions.h
instead.std::weak_ptr<int> x = my_shared_x;
Description: Allows a weak reference to a std::shared_ptr
.
Documentation: std::weak_ptr
Notes:
std::shared_ptr
is banned. Use base::WeakPtr
instead.#include <barrier> // C++20 #include <condition_variable> #include <future> #include <latch> // C++20 #include <mutex> #include <semaphore> // C++20 #include <stop_token> // C++20 #include <thread>
Description: Provides a standard multithreading library using std::thread
and associates
Documentation: Thread support library
Notes:
base/synchronization
. base::Thread
is tightly coupled to base::MessageLoop
which would make it hard to replace. We should investigate using standard mutexes, or unique_lock, etc. to replace our locking/synchronization classes.The following C++17 language features are allowed in the Chromium codebase.
template <typename T> struct MyContainer { MyContainer(T val) : val{val} {} // ... }; MyContainer c1(1); // Type deduced to be `int`.
Description: Automatic template argument deduction much like how it's done for functions, but now including class constructors.
Documentation: Class template argument deduction
Notes:
if constexpr (cond) { ...
Description: Write code that is instantiated depending on a compile-time condition.
Documentation: if
statement
Notes:
auto identity = [](int n) constexpr { return n; }; static_assert(identity(123) == 123);
Description: Compile-time lambdas using constexpr.
Documentation: Lambda expressions
Notes:
template <auto... seq> struct my_integer_sequence { // ... }; auto seq = my_integer_sequence<0, 1, 2>(); // Type deduced to be `int`.
Description: Following the deduction rules of auto
, while respecting the non-type template parameter list of allowable types, template arguments can be deduced from the types of its arguments.
Documentation: Template parameters
Notes:
case 1: DoSomething(); [[fallthrough]]; case 2: break;
Description: The [[fallthrough]]
attribute can be used in switch statements to indicate when intentionally falling through to the next case.
Documentation: C++ attribute: fallthrough
Notes:
template <typename... Args> auto sum(Args... args) { return (... + args); }
Description: A fold expression performs a fold of a template parameter pack over a binary operator.
Documentation: Fold expression
Notes:
struct S { static constexpr int kZero = 0; // constexpr implies inline here. }; inline constexpr int kOne = 1; // Explicit inline needed here.
Description: The inline
specifier can be applied to variables as well as to functions. A variable declared inline has the same semantics as a function declared inline. It can also be used to declare and define a static member variable, such that it does not need to be initialized in the source file.
Documentation: inline
specifier
Notes:
Inline variables in anonymous namespaces in header files will still get one copy per translation unit, so they must be outside of an anonymous namespace to be effective.
Mutable inline variables and taking the address of inline variables are banned since these will break the component build.
#if __has_include(<optional>) ...
Description: Checks whether a file is available for inclusion, i.e. the file exists.
Documentation: Source file inclusion
Notes:
const auto l = [*this] { return member_; }
Description: *this
captures the current object by copy, while this
continues to capture by reference.
Documentation: Lambda capture
Notes:
struct [[maybe_unused]] MyUnusedThing; [[maybe_unused]] int x;
Description: The [[maybe_unused]]
attribute can be used to indicate that individual variables, functions, or fields of a class/struct/enum can be left unused.
Documentation: C++ attribute: maybe_unused
Notes:
namespace A::B::C { ...
Description: Using the namespace resolution operator to create nested namespace definitions.
Documentation: Namespaces
Notes:
struct [[nodiscard]] ErrorOrValue; [[nodiscard]] bool DoSomething();
Description: The [[nodiscard]]
attribute can be used to indicate that
Documentation: C++ attribute: nodiscard
Notes:
This replaces the previous WARN_UNUSED_RESULT
macro, which was a wrapper around the compiler-specific __attribute__((warn_unused_result))
.
if (int a = Func(); a < 3) { ... switch (int a = Func(); a) { ...
Description: New versions of the if and switch statements which simplify common code patterns and help users keep scopes tight.
Documentation: if
statement, switch
statement
Notes:
const auto [x, y] = FuncReturningStdPair();
Description: Allows writing auto [x, y, z] = expr;
where the type of expr
is a tuple-like object, whose elements are bound to the variables x
, y
, and z
(which this construct declares). Tuple-like objects include std::tuple
, std::pair
, std::array
, and aggregate structures.
Documentation: Structured binding declaration Explanation of structured binding types
Notes:
In C++17, structured bindings don't work with lambda captures. C++20 will allow capturing structured bindings by value.
This feature forces omitting type names. Its use should follow the guidance around auto
in Google C++ Style guide.
[[using CC: opt(1), debug]] // same as [[CC:opt(1), CC::debug]]
Description: Specifies a common namespace for a list of attributes.
Documentation: Attribute specifier sequence
Notes:
The following C++17 language features are allowed in the Chromium codebase.
double dist = std::hypot(1.0, 2.5, 3.7);
Description: Computes the distance from the origin in 3D space.
Documentation: std::hypot
Notes:
auto it = std::search(haystack.begin(), haystack.end(), std::boyer_moore_searcher(needle.begin(), needle.end()));
Description: Alternate string searching algorithms.
Documentation: Searchers
Notes:
static_assert(std::apply(std::plus<>(), std::make_tuple(1, 2)) == 3);
Description: Invokes a Callable
object with a tuple of arguments.
Documentation: std::apply
Notes:
auto&& const_ref = std::as_const(mutable_obj);
Description: Forms reference to const T.
Documentation: std::as_const
Notes:
template <typename T> struct is_lock_free_impl : std::integral_constant<bool, std::atomic<T>::is_always_lock_free> {};
Description: True when the given atomic type is always lock-free.
Documentation: std::atomic<T>::is_always_lock_free
Notes:
int x = std::clamp(inp, 0, 100);
Description: Clamps a value between a minimum and a maximum.
Documentation: std::clamp
template<typename T, typename... Ts> std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...>> func(T, Ts...) { ...
Description: Performs logical operations on type traits.
Documentation: std::conjunction
, std::disjunction
, std::negation
Notes:
std::exclusive_scan(data.begin(), data.end(), output.begin());
Description: Like std::inclusive_scan
but omits the current element from the written output at each step; that is, results are “one value behind” those of std::inclusive_scan
.
Documentation: std::exclusive_scan
Notes:
static_assert(std::gcd(12, 18) == 6);
Description: Computes the greatest common divisor of its arguments.
Documentation: std::gcd
Notes:
std::has_unique_object_representations_v<foo>
Description: Checks wither the given type is trivially copyable and any two objects with the same value have the same object representation.
Documentation: std::has_unique_object_representations
Notes:
std::inclusive_scan(data.begin(), data.end(), output.begin());
Description: Like std::accumulate
but writes the result at each step into the output range.
Documentation: std::inclusive_scan
Notes:
static_assert(std::invoke(std::plus<>(), 1, 2) == 3);
Description: Invokes a callable object with parameters. A callable object is e.g. a function, function pointer, functor (that is, an object that provides operator()
), lambda, etc.
Documentation: std::invoke
Notes:
if constexpr(std::is_aggregate_v<T>) { ...
Description: Checks wither the given type is an aggregate type.
Documentation: std::is_aggregate
Notes:
std::is_invocable_v<Fn, 1, "Hello">
Description: Checks whether a function may be invoked with the given argument types. The _r
variant also evaluates whether the result is convertible to a given type.
Documentation: std::is_invocable
Notes:
std::is_swappable<T> std::is_swappable_with_v<T, U>
Description: Checks whether classes may be swapped.
Documentation: std::is_swappable
Notes:
struct Y { int z; }; alignas(Y) std::byte s[sizeof(Y)]; Y* q = new(&s) Y{2}; const int h = std::launder(reinterpret_cast<Y*>(&s))->z;
Description: When used to wrap a pointer, makes it valid to access the resulting object in cases it otherwise wouldn't have been, in a very limited set of circumstances.
Documentation: std::launder
Notes:
static_assert(std::lcm(12, 18) == 36);
Description: Computes the least common multiple of its arguments.
Documentation: std::lcm
Notes:
// Calls Foo(int, double): auto foo = std::make_from_tuple<Foo>(std::make_tuple(1, 3.5));
Description: Constructs an object from a tuple of arguments.
Documentation: std::make_from_tuple
Notes:
std::map<...>::extract std::map<...>::merge std::set<...>::extract std::set<...>::merge
Description: Moving nodes and merging containers without the overhead of expensive copies, moves, or heap allocations/deallocations.
Documentation: std::map::extract
, std::map::merge
Notes:
std::map<std::string, std::string> m; m.insert_or_assign("c", "cherry"); m.insert_or_assign("c", "clementine");
Description: Like operator[]
, but returns more information and does not require default-constructibility of the mapped type.
Documentation: std::map::insert_or_assign
Notes:
std::map<std::string, std::string> m; m.try_emplace("c", 10, 'c'); m.try_emplace("c", "Won't be inserted");
Description: Like emplace
, but does not move from rvalue arguments if the insertion does not happen.
Documentation: std::map::try_emplace
,
Notes:
auto nonwhite = std::find_if(str.begin(), str.end(), std::not_fn(IsWhitespace));
Description: Creates a forwarding call wrapper that returns the negation of the callable object it holds.
Documentation: std::not_fn
Notes:
char buffer[260]; memcpy(std::data(buffer), source_str.data(), std::size(buffer)); if (!std::empty(container)) { ... }
Description: Non-member versions of what are often member functions on STL containers. Primarily useful when:
std::size()
as a replacement for the old arraysize()
macro.std::vector
and std::list
(which provide size()
, empty()
, and data() member functions),
std::arrayand
std::initialize_list` (which only provide a subset of the aforementioned member functions), and regular arrays (which have no member functions at all).Documentation: std::size
, std::empty
, std::data
Notes:
Prefer range-based for loops over std::size()
: range-based for loops work even for regular arrays.
bool b = std::is_same_v<int, std::int32_t>;
Description: Syntactic sugar to provide convenient access to ::value
members by simply adding _v
.
Documentation: Type support
Notes:
std::destroy(ptr, ptr + 8); std::destroy_at(ptr); std::destroy_n(ptr, 8); std::uninitialized_move(src.begin(), src.end(), dest.begin()); std::uninitialized_value_construct(std::begin(storage), std::end(storage));
Description: Replaces direct constructor and destructor calls when manually managing memory.
Documentation: std::destroy
, std::destroy_at
, std::destroy_n
, std::uninitialized_move
, std::uninitialized_value_construct
Notes:
The following C++17 library features are not allowed in the Chromium codebase.
int* p2 = static_cast<int*>(std::aligned_alloc(1024, 1024));
Description: Allocates uninitialized storage with the specified alignment.
Documentation: std::aligned_alloc
Notes:
base::AlignedAlloc
.std::any x = 5;
Description: A type-safe container for single values of any type.
Documentation: std::any
Notes:
Banned since workaround for lack of RTTI isn't compatible with the component build (Bug). Also see absl::any
.
#include <filesystem>
Description: A standard way to manipulate files, directories, and paths in a filesystem.
Documentation: Filesystem library
Notes:
struct SharedData { ReadOnlyFrequentlyUsed data; alignas(std::hardware_destructive_interference_size) std::atomic<size_t> counter; };
Description: The std::hardware_destructive_interference_size
constant is useful to avoid false sharing (destructive interference) between variables that would otherwise occupy the same cacheline. In contrast, std::hardware_constructive_interference_size
is helpful to promote true sharing (constructive interference), e.g. to support better locality for non-contended data.
Documentation: std::hardware_destructive_interference_size
, std::hardware_constructive_interference_size
Notes:
std::optional<std::complex<double>> opt{std::in_place, 0, 1}; std::variant<int, float> v{std::in_place_type<int>, 1.4};
Description: The std::in_place
are disambiguation tags for std::optional
, std::variant
, and std::any
to indicate that the object should be constructed in-place.
Documentation: std::in_place
Notes:
std::optional
, std::variant
, and std::any
are all banned for now. Because absl::optional
and absl::variant
are used instead, and they require absl::in_place
, use absl::in_place
for non-Abseil Chromium code. See the discussion thread.std::optional<std::string> s;
Description: The class template std::optional
manages an optional contained value, i.e. a value that may or may not be present. A common use case for optional is the return value of a function that may fail.
Documentation: std::optional
Notes:
absl::optional
.std::string_view str = "foo"; std::u16string_view str16 = u"bar";
Description: A non-owning reference to a string. Useful for providing an abstraction on top of strings (e.g. for parsing).
Documentation: std::basic_string_view
Notes:
base::StringPiece[16]
, unless interfacing with third-party code, in which case it is allowed. Note base::StringPiece[16]
implicitly convert to and from the corresponding STL types, so one typically does not need to write the STL name.int count = std::uncaught_exceptions();
Description: Determines whether there are live exception objects.
Documentation: std::uncaught_exceptions
Notes:
std::variant<int, double> v = 12;
Description: The class template std::variant
represents a type-safe union
. An instance of std::variant
at any given time holds a value of one of its alternative types (it's also possible for it to be valueless).
Documentation: std::variant
Notes:
absl::variant
.std::map<std::weak_ptr<T>, U, std::owner_less<>>
Description: Function object providing mixed-type owner-based ordering of shared and weak pointers, regardless of the type of the pointee.
Documentation: std::owner_less
Notes:
std::shared_ptr
and std::weak_ptr
are banned.auto weak_ptr = weak_from_this();
Description: Returns a std::weak_ptr<T>
that tracks ownership of *this
by all existing std::shared_ptr
s that refer to *this
.
Documentation: std::enable_shared_from_this<T>::weak_from_this
Notes:
std::shared_ptr
and std::weak_ptr
are banned.The following C++17 language features are not allowed in the Chromium codebase. See the top of this page on how to propose moving a feature from this list into the allowed or banned sections.
char x = u8'x'; // C++17 char8_t x = u8'x'; // C++20
Description: A character literal that begins with u8
is a character literal of type char
(C++17) or char8_t
(C++20). The value of a UTF-8 character literal is equal to its ISO 10646 code point value.
Documentation: Character literal
Notes:
The following C++17 library features are not allowed in the Chromium codebase. See the top of this page on how to propose moving a feature from this list into the allowed or banned sections.
std::assoc_laguerre() std::assoc_legendre() std::beta() std::comp_ellint_1() std::comp_ellint_2() std::comp_ellint_3() std::cyl_bessel_i() std::cyl_bessel_j() std::cyl_bessel_k() std::cyl_neumann() std::ellint_1() std::ellint_2() std::ellint_3() std::expint() std::hermite() std::legendre() std::laguerre() std::riemann_zeta() std::sph_bessel() std::sph_legendre() std::sph_neumann()
Description: A variety of mathematical functions.
Documentation: Mathematical special functions
Notes:
auto it = std::find(std::execution::par, std::begin(vec), std::end(vec), 2);
Description: Many of the STL algorithms, such as the copy
, find
and sort
methods, now support the parallel execution policies: seq
, par
, and par_unseq
which translate to “sequentially”, “parallel” and “parallel unsequenced”.
Notes:
std::byte b = 0xFF; int i = std::to_integer<int>(b); // 0xFF
Description: A standard way of representing data as a byte. std::byte
is neither a character type nor an arithmetic type, and the only operator overloads available are bitwise operations.
Documentation: std::byte
Notes:
#include <memory_resource>
Description: Manages memory allocations using runtime polymorphism.
Documentation: std::pmr::memory_resource
, std::pmr::polymorphic_allocator
Notes:
std::reduce(std::execution::par, v.cbegin(), v.cend());
Description: Like std::accumulate
except the elements of the range may be grouped and rearranged in arbitrary order.
Documentation: std::reduce
Notes:
std::execution::par
.std::timespec ts; std::timespec_get(&ts, TIME_UTC);
Description: Gets the current calendar time in the given time base.
Documentation: std::timespec_get
Notes:
std::from_chars(str.data(), str.data() + str.size(), result); std::to_chars(str.data(), str.data() + str.size(), 42);
Description: Locale-independent, non-allocating, non-throwing functions to convert values from/to character strings, designed for use in high-throughput contexts.
Documentation: std::from_chars
std::to_chars
,
Notes:
struct S { int x = 1; int y = 2; } S s{ .y = 3 }; // OK, s.x == 1, s.y == 3
Description: Allows explicit initialization of subsets of aggregate members at construction.
Documentation: Designated initializers
Notes:
The following Abseil library features are not allowed in the Chromium codebase.
absl::any a = int{5}; EXPECT_THAT(absl::any_cast<int>(&a), Pointee(5)); EXPECT_EQ(absl::any_cast<size_t>(&a), nullptr);
Description: Early adaptation of C++17 std::any
.
Documentation: std::any
Notes:
std::any
.absl::bind_front
Description: Binds the first N arguments of an invocable object and stores them by value.
Documentation:
Notes:
base::Bind
. Use base::Bind
instead.ABSL_FLAG(bool, logs, false, "print logs to stderr"); app --logs=true;
Description: Allows programmatic access to flag values passed on the command-line to binaries.
Documentation: Flags Library
Notes:
base::CommandLine
instead.auto it = absl::c_find(container, value);
Description: Container-based versions of algorithmic functions within C++ standard library.
Documentation: container.h
Notes:
base/ranges/algorithm.h
. Use the base/ranges/
facilities instead.absl::FunctionRef
Description: Type for holding a non-owning reference to an object of any invocable type.
Documentation: function_ref.h
Notes:
absl::FunctionRef
is banned due to allowing implicit conversions between function signatures in potentially surprising ways. For example, a callable with the signature int()
will bind to absl::FunctionRef<void()>
: the return value from the callable will be silently discarded.base::FunctionRef
instead.base::OnceCallback
and base::RepeatingCallback
, base::FunctionRef
supports capturing lambdas.ForEachFrame(base::FunctionRef<void(Frame&)>)
. This can often result in clearer code than code that is templated to accept lambdas, e.g. with template <typename Invocable> void ForEachFrame(Invocable invocable)
, it is much less obvious what arguments will be passed to invocable
.base::OnceCallback
and base::RepeatingCallback
intentionally disallow conversions to base::FunctionRef
, under the theory that the callback should be a capturing lambda instead. Attempting to use this conversion will trigger a static_assert
requesting additional feedback for use cases where this conversion would be valuable.base::FunctionRef
must not outlive the function call. Like base::StringPiece
, base::FunctionRef
is a non-owning reference. Using a base::FunctionRef
as a return value or class field is dangerous and likely to result in lifetime bugs.absl::BitGen bitgen; size_t index = absl::Uniform(bitgen, 0u, elems.size());
Description: Functions and utilities for generating pseudorandom data.
Documentation: Random library
Notes:
base/rand_util.h
instead.absl::Span
Description: Early adaptation of C++20 std::span
.
Documentation: Using absl::Span
Notes:
base::span
. Keep using base::span
.absl::StatusOr<T>
Description: An object that is either a usable value, or an error Status explaining why such a value is not present.
Documentation: statusor.h
Notes:
base::expected
. Use base::expected
instead.absl::StrFormat
Description: A typesafe replacement for the family of printf() string formatting routines.
Documentation: String Formatting
Notes:
base::StringPrintf()
. See migration bug.absl::string_view
Description: Early adaptation of C++17 std::string_view
.
Documentation: absl::string_view
Notes:
std::string_view
. Use base::StringPiece
from base/strings/
, unless interfacing with third-party code, in which case prefer to write the type as std::string_view
. Note base::StringPiece
implicitly converts to and from std::string_view
, so one typically does not need to write the STL name.absl::StrSplit absl::StrJoin absl::StrCat absl::StrAppend absl::Substitute absl::StrContains
Description: Classes and utility functions for manipulating and comparing strings.
Documentation: String Utilities
Notes:
base/strings
. We should re-evalute when we've migrated from base::StringPiece
to std::string_view
.absl::Mutex
Description: Primitives for managing tasks across different threads.
Documentation: Synchronization
Notes:
base/synchronization/
. We would love more testing on whether there are compelling reasons to prefer base, absl, or std synchronization primitives; for now, use base/synchronization/
.absl::Duration absl::Time absl::TimeZone absl::CivilDay
Description: Abstractions for holding time values, both in terms of absolute time and civil time.
Documentation: Time
Notes:
base/time/
. Use base/time/
instead.The following Abseil library features are not allowed in the Chromium codebase. See the top of this page on how to propose moving a feature from this list into the allowed or banned sections.
absl::AnyInvocable
Description: An equivalent of the C++23 std::move_only_function.
Documentation:
Notes:
base::RepeatingCallback
, base::OnceCallback
.absl::flat_hash_map absl::flat_hash_set absl::node_hash_map absl::node_hash_set absl::btree_map absl::btree_set absl::btree_multimap absl::btree_multiset absl::InlinedVector absl::FixedArray
Description: Alternatives to STL containers designed to be more efficient in the general case.
Documentation:
Notes:
base/containers/
.Description: API for computing CRC32C values as checksums for arbitrary sequences of bytes provided as a string buffer.
Documentation: crc32.h
Notes:
LOG(INFO) << message; CHECK(condition); absl::AddLogSink(&custom_sink_to_capture_absl_logs);
Description: Macros and related classes to perform debug loggings
Notes:
base/logging.h
.