Skip to content

74 Advanced The Hundred

One Brace, Two Meanings

same braces, same 42, one stray =

#include <initializer_list>
#include <iostream>
#include <type_traits>

int main() {
    auto a{42};      // braces are the modern way to initialize, right?
    auto b = {42};   // same thing, spelled with an equals sign

    std::cout << "sizeof(a) = " << sizeof(a) << "\n";
    std::cout << "sizeof(b) = " << sizeof(b) << "\n";

    // compile-time proof of what was deduced:
    static_assert(std::is_same_v<decltype(a), int>);
    static_assert(std::is_same_v<decltype(b), std::initializer_list<int>>);
}

Run it. Which of the two static_asserts fails — and what two sizes does it print?

Answer

Neither: both hold. That one = is the whole difference, and the program prints:

sizeof(a) = 4
sizeof(b) = 16

Why

A braced list has no type of its own, so auto needed a special deduction rule — and it got two. The direct form auto a{42} unwraps the single element and deduces int; the copy form auto b = {42} wraps it and deduces std::initializer_list<int>, a pointer-plus-length view of a hidden temporary array — hence 16 bytes on a 64-bit target. -Wall -Wextra has nothing to say about any of it. The direct form is also strict: exactly one element, so -DSHOW_BUG adds auto c{1, 2}; and GCC 11 refuses — while cheerfully naming the = as the switch:

error: direct-list-initialization of ‘auto’ requires exactly one element
note: for deduction to ‘std::initializer_list’, use copy-list-initialization
      (i.e. add ‘=’ before the ‘{’)

Before N3922 (C++17, applied retroactively — GCC 11 deduces this way even in -std=c++11) both forms deduced initializer_list.

The fix

auto a = 42;                        // int — no braces, no doubt
std::initializer_list<int> b{42};   // want a list? say the type

Takeaway: never combine auto with braces — unless you truly want an initializer_list, and then write the type out.

Try it: g++ -std=c++17 main.cpp -o demo && ./demo — then again with -DSHOW_BUG

Open in Compiler Explorer ↗ Open SHOW_BUG variant ↗ Quiz this entry