optional, variant, any
Coddy C++ 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 104개 중 89번째.
Modern C++는 <optional>, <variant>, <any> 헤더에서 값이 없을 수도 있거나, 여러 타입 중 하나를 보유하거나, 어떤 타입이든 저장할 수 있는 값을 처리하는 데 도움이 되는 세 가지 어휘 타입을 제공합니다.
std::optional<T>은 존재할 수도 있고 존재하지 않을 수도 있는 값을 나타냅니다. 예외를 발생시키지 않고 실패할 수 있는 함수에 적합합니다:
#include <iostream>
#include <optional>
std::optional<int> findIndex(const std::string& str, char c) {
for (size_t i = 0; i < str.size(); ++i) {
if (str[i] == c) return i;
}
return std::nullopt; // 값 없음
}
int main() {
auto result = findIndex("hello", 'l');
if (result.has_value()) {
std::cout << "Found at: " << *result << "\n"; // 2
}
}std::variant<Types...>는 지정된 타입 중 정확히 하나를 언제든 보유하는 타입 안전 유니온입니다:
#include <iostream>
#include <variant>
#include <string>
int main() {
std::variant<int, double, std::string> data;
data = 42;
std::cout << std::get<int>(data) << "\n";
data = "hello";
if (std::holds_alternative<std::string>(data)) {
std::cout << std::get<std::string>(data) << "\n";
}
}std::any는 런타임에 결정되는 모든 유형의 값을 보유할 수 있습니다. 값을 가져오려면 std::any_cast를 사용하세요.
#include <iostream>
#include <any>
int main() {
std::any value = 10;
std::cout << std::any_cast<int>(value) << "\n";
value = std::string("text");
std::cout << std::any_cast<std::string>(value) << "\n";
}null이 될 수 있는 값에는 std::optional을 선택하고, 컴파일 시점에 가능한 타입을 알고 있다면 std::variant를 사용하며, 런타임 타입 유연성이 정말 필요할 때만 std::any를 사용하세요.
챌린지
쉬움현대 C++ 어휘 타입의 강력한 기능을 보여 주는 구성 시스템을 만들어 보겠습니다. 값이 없을 수도 있고, 다양한 타입을 저장할 수도 있으며, 런타임에 타입을 유연하게 처리해야 하는 설정 관리자를 만들게 됩니다.
코드를 세 개의 파일로 구성합니다:
ConfigTypes.h: 구성 값 타입과 도우미 함수를 정의합니다.문자열을 받아 정수로 파싱을 시도하는
parseValue함수를 만드세요. 문자열이 유효한 정수를 나타내면 정수를std::optional로 감싸서 반환합니다. 파싱에 실패하면(문자열에 숫자가 아닌 문자가 포함된 경우)std::nullopt를 반환합니다. 간단하게 하기 위해 문자열에 숫자만 포함되어 있거나 앞에 선택적으로 마이너스 기호가 포함되어 있으면 유효한 문자열로 간주하세요.int,double,std::string중 하나를 저장할 수 있는std::variant를 사용하여Setting이라는 타입 별칭도 만드세요.마지막으로
Setting을 받아 어떤 타입을 저장하고 있는지와 그 값을 다음 형식의 문자열로 설명하여 반환하는describeSetting함수를 만드세요:- int인 경우:
Integer: [value] - double인 경우:
Double: [value] - string인 경우:
String: [value]
- int인 경우:
DynamicStore.h:std::any를 사용하여 간단한 키-값 저장소를 만드세요.모든 타입의 값을 저장할 수 있는
DynamicStore클래스를 정의하세요. 다음 항목을 포함해야 합니다:- 문자열 키와
std::any값을 받아 내부에 저장하는set메서드(std::map을 사용하세요) - 키를 받아
std::any값을 반환하는get메서드(키가 존재하지 않으면 빈std::any를 반환합니다) - 키가 존재하면 true를 반환하는
hasKey메서드
- 문자열 키와
main.cpp: 세 개의 입력을 읽습니다:- 숫자일 수도 있는 문자열(
std::optional테스트용) - 타입 표시자:
int,double또는string - 해당 타입에 맞는 값
세 가지 어휘 타입을 모두 시연하세요:
먼저 첫 번째 입력에
parseValue함수를 사용하세요. 값이 포함되어 있으면Parsed: [value]를 출력합니다. 비어 있으면Parse failed를 출력합니다.두 번째로 타입 표시자에 따라
Settingvariant를 만드세요. 타입이int이면 값을 정수로 저장합니다.double이면 double로 저장합니다.string이면 문자열로 저장합니다. 그런 다음describeSetting을 호출하고 결과를 출력하세요.세 번째로
DynamicStore를 만들고, 키"status"아래에 문자열"config_loaded"를 저장한 다음 이를 검색하여Status: [value]를 출력하세요. 값을 추출하려면std::any_cast<std::string>을 사용하세요.- 숫자일 수도 있는 문자열(
예를 들어 입력이 42, int, 100인 경우:
Parsed: 42
Integer: 100
Status: config_loaded입력이 hello, double, 3.14인 경우:
Parse failed
Double: 3.14
Status: config_loaded입력이 -15, string, username인 경우:
Parsed: -15
String: username
Status: config_loaded필요한 곳에 적절한 헤더인 <optional>, <variant>, <any>, <string>, <map>을 포함해야 합니다. variant를 다루려면 std::holds_alternative와 std::get을 사용하고, optional을 확인하려면 has_value() 또는 직접적인 불리언 변환을 사용하세요.
직접 해보기
#include <iostream>
#include <string>
#include <any>
#include "ConfigTypes.h"
#include "DynamicStore.h"
int main() {
// 세 개의 입력을 읽기
std::string input1; // 숫자일 수 있는 문자열 (std::optional 테스트용)
std::string typeIndicator; // 타입 표시자: int, double 또는 string
std::string value; // 해당 타입에 대응하는 값
std::cin >> input1;
std::cin >> typeIndicator;
std::cin >> value;
// TODO: Part 1 - parseValue로 std::optional 테스트
// input1과 함께 parseValue 함수 사용
// 값이 포함되어 있으면 "Parsed: [value]" 출력
// If it's empty, print "Parse failed"
// TODO: Part 2 - Setting으로 std::variant 테스트
// typeIndicator를 기반으로 Setting variant 생성
// 타입이 "int"이면 value를 정수로 저장
// 타입이 "double"이면 value를 double로 저장
// 타입이 "string"이면 value를 문자열로 저장
// 그런 다음 describeSetting을 호출하고 결과를 출력합니다
// TODO: Part 3 - DynamicStore로 std::any 테스트
// DynamicStore 생성
// 키 "status" 아래에 문자열 "config_loaded"를 저장
// 이를 가져와 출력: "Status: [value]"
// 값을 추출하려면 std::any_cast<std::string>을 사용
return 0;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 C++ 컴파일러