15. std::variant 와 std::visit 의 내부 동작
난이도 상 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C++
// ─────────────────────────────────────────────────────────────
// 주제: std::variant 와 std::visit 의 내부 동작
//
// 게임 서버에서 여러 종류의 메시지를 하나의 타입(Msg)으로 다루기 위해
// std::variant 를 쓴다. 아래 코드를 보고 실행 전에 예측하라.
//
// 과제:
// 1) main 의 출력(각 줄)을 정확히 예측하라. 특히 index() 값의 변화,
// holds_alternative 결과, 그리고 sizeof(Msg) 가 어떻게 결정되는지.
// 2) std::variant 가 "어느 대안을 담고 있는지"를 내부적으로 어떻게 기록하며,
// std::visit 가 런타임에 올바른 람다를 고르는 메커니즘(점프 테이블)을 설명하라.
// 3) variant 에 새 값을 대입하던 도중 예외가 나면 어떤 상태가 될 수 있는지
// (valueless_by_exception) 설명하라.
// (내부 동작 설명은 answer.md 에서. 여기서는 예측만.)
// ─────────────────────────────────────────────────────────────
#include <variant>
#include <string>
#include <iostream>
struct Move { int x, y; };
struct Chat { std::string text; };
struct Attack { int targetId; };
using Msg = std::variant<Move, Chat, Attack>;
template <class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
std::string handle(const Msg& m) {
return std::visit(overloaded{
[](const Move& mv){ return std::string("Move:") + std::to_string(mv.x); },
[](const Chat& c ){ return std::string("Chat:") + c.text; },
[](const Attack& a ){ return std::string("Attack:") + std::to_string(a.targetId); }
}, m);
}
int main() {
Msg m = Move{3, 4};
std::cout << m.index() << " " << handle(m) << "\n";
m = Chat{"hi"};
std::cout << m.index() << " " << handle(m) << "\n";
m = Attack{42};
std::cout << m.index() << " " << handle(m) << "\n";
std::cout << std::boolalpha
<< "holds<Chat>=" << std::holds_alternative<Chat>(m) << "\n";
std::cout << "sizeof(Msg)=" << sizeof(Msg) << "\n";
return 0;
} 내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.