0Pricing
C++ Academy · Lesson

std::variant

A type-safe union.

std::variant is a free C++ Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C++ Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

A Type-Safe Union

std::variant holds exactly one value out of a fixed list of types and remembers which one. Include <variant> to use it.

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 10;
    std::cout << std::get<int>(v) << "\n";
}

Assigning Different Types

You can reassign a variant to any of its alternative types. It updates which alternative is active automatically.

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 5;
    v = 3.14; // now holds a double
    std::cout << std::get<double>(v) << "\n";
}

Checking the Active Type

std::holds_alternative<T>(v) tells you whether the variant currently holds type T.

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 2.0;
    std::cout << std::holds_alternative<double>(v) << "\n";
    std::cout << std::holds_alternative<int>(v) << "\n";
}

The index() Function

v.index() returns the zero-based position of the active type in the type list.

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double, char> v = (char)65;
    std::cout << v.index() << "\n"; // 2
}

Safe Access with std::get

std::get<T> returns the value if T is active, otherwise it throws std::bad_variant_access. No silent garbage.

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 7;
    try {
        std::cout << std::get<double>(v) << "\n";
    } catch (const std::bad_variant_access& e) {
        std::cout << "wrong type!\n";
    }
}

Non-Throwing get_if

std::get_if<T>(&v) returns a pointer to the value or nullptr if T is not active. Great for branchless checks.

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 9;
    if (auto p = std::get_if<int>(&v))
        std::cout << "int " << *p << "\n";
}

Default Construction

A default-constructed variant holds a value-initialized version of its first type. Order your types so the first makes a sensible default.

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v; // holds int 0
    std::cout << std::get<int>(v) << "\n";
}

Storing Strings

Unlike raw unions, a variant can safely hold non-trivial types such as std::string; lifetime is managed for you.

#include <iostream>
#include <string>
#include <variant>
int main() {
    std::variant<int, std::string> v = std::string("hello");
    std::cout << std::get<std::string>(v) << "\n";
}

Variant as a Return Type

A function can return one of several types by returning a variant. Callers then inspect it to discover which type came back.

#include <iostream>
#include <string>
#include <variant>
std::variant<int, std::string> parse(bool ok) {
    if (ok) return 42;
    return std::string("error");
}
int main() {
    auto r = parse(false);
    if (auto s = std::get_if<std::string>(&r)) std::cout << *s << "\n";
}

emplace for In-Place Change

v.emplace<T>(args...) constructs a new value of type T directly inside the variant, switching the active alternative.

#include <iostream>
#include <string>
#include <variant>
int main() {
    std::variant<int, std::string> v = 1;
    v.emplace<std::string>("switched");
    std::cout << std::get<std::string>(v) << "\n";
}

Why Prefer Variant?

std::variant gives you union memory efficiency with full type safety: it tracks the active type, manages lifetimes, and refuses wrong-type access. The next lesson shows the cleanest way to process it.

Quick Check

Check your understanding of std::variant.

Recap

You learned std::variant:

  • Holds one of several types and tracks which.
  • holds_alternative / index() inspect the active type.
  • std::get throws on mismatch; get_if returns a pointer or null.
  • Safely stores non-trivial types like std::string.

Frequently asked questions

Is the “std::variant” lesson free?

Yes — the full text of “std::variant” is free to read here on the web, and the C++ Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C++ Academy course, upgrade to CoddyKit PRO.

What will I learn in “std::variant”?

A type-safe union. You practise C++ Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C++ Academy?

No prior experience is required. C++ Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “std::variant” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C++ Academy lesson?

Yes. Every C++ Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Scoped enum class
  2. Unions and Their Risks
  3. std::variant
  4. std::visit
← Back to C++ Academy