CodeNebula
C++26coreexpert

Placeholder Variables with Multiple _

C++26 · The Next Frontier · Compiler flag: -std=c++26

Explanation

Allows using the identifier `_` as a placeholder for variables that are intentionally unused. Multiple declarations of `_` in the same scope do not conflict, making it clear that the values are discarded.

Real-World Scenario

When destructuring a complex struct, ignore irrelevant fields cleanly without triggering compiler warnings.

Quick Snippet

snippet.cpp
auto [x, _, _, w] = std::tuple{1, 2, 3, 4}; // Ignore second and third elements
// x == 1, w == 4; both _ bindings are discarded

for (auto [key, _] : my_map) {
    process(key); // Only the key matters
}

Full Example

placeholder_variables.cpp
// CodeNebula - C++26 Example: Placeholder Variables
// Compile: g++ -std=c++26 -Wall -Wextra -o example placeholder_variables.cpp
// Note: Requires C++26 compiler support (GCC 15+ / Clang 19+ expected)

// C++26 allows using _ as a placeholder variable name multiple times
// in the same scope. Each _ is a unique unnamed variable. This is useful
// for ignoring values in structured bindings, locks, RAII guards, etc.

#include <iostream>
#include <tuple>
#include <map>
#include <mutex>

// --- C++26 Placeholder Syntax ---
//
// auto [_, value, _] = std::tuple{1, "hello", 3.14};
// // Both _ are separate unnamed variables; only 'value' is usable
//
// std::lock_guard _(mutex1);  // unnamed lock
// std::lock_guard _(mutex2);  // another unnamed lock, same scope!
//
// for (auto [_, v] : my_map) { /* use v, ignore key */ }

// --- Simulation using C++20 features ---

// In C++20, we must use unique names or [[maybe_unused]]
struct Point3D { int x; int y; int z; };

int main() {
    std::cout << "=== C++26 Placeholder Variables (Simulated) ===" << std::endl;

    // C++26: auto [_, value, _] = std::tuple{1, "hello", 3.14};
    // Simulation: use unique placeholder names
    auto [_1, value, _2] = std::tuple{1, std::string("hello"), 3.14};
    (void)_1; (void)_2; // suppress unused warnings
    std::cout << "Extracted value: " << value << std::endl;

    // C++26: for (auto [_, v] : map) { ... }
    std::map<int, std::string> colors{{1, "red"}, {2, "green"}, {3, "blue"}};
    std::cout << "Map values (keys ignored):" << std::endl;
    for (auto [_key, v] : colors) {
        (void)_key;
        std::cout << "  " << v << std::endl;
    }

    // C++26: multiple RAII guards with _ name
    std::mutex m1, m2;
    {
        // C++26: std::lock_guard _(m1); std::lock_guard _(m2);
        std::lock_guard lock1(m1); // Simulation: unique names
        std::lock_guard lock2(m2);
        std::cout << "Both mutexes locked (two _ guards in C++26)" << std::endl;
    }

    // C++26: auto [x, _, _] = Point3D{10, 20, 30};
    auto [x, _y, _z] = Point3D{10, 20, 30};
    (void)_y; (void)_z;
    std::cout << "Point3D x only: " << x << std::endl;

    std::cout << "Placeholder _ reduces noise for intentionally unused variables."
              << std::endl;
    return 0;
}

// Expected output:
// === C++26 Placeholder Variables (Simulated) ===
// Extracted value: hello
// Map values (keys ignored):
//   red
//   green
//   blue
// Both mutexes locked (two _ guards in C++26)
// Point3D x only: 10
// Placeholder _ reduces noise for intentionally unused variables.
Run command
g++ -std=c++26 -Wall -Wextra -o example placeholder_variables.cpp