2026-09-18
describe_value.cpp
#include <string>
#include <variant>
using Value = std::variant<int, double, std::string>;
std::string describe(const Value& v) {
// write this: using std::visit with a single generic lambda and
// if constexpr (no overloaded helper struct), return "int:3",
// "double:2.5" or "string:hi" depending on which alternative v holds
}
describeを実装してください。overloadedヘルパーは使わず、std::visitには1つのジェネリックラムダだけを渡し、その中でif constexprを使って型ごとに分岐すること。
Reference
std::string describe(const Value& v) {
return std::visit([](const auto& x) -> std::string {
using T = std::decay_t<decltype(x)>;
if constexpr (std::is_same_v<T, int>) {
return "int:" + std::to_string(x);
} else if constexpr (std::is_same_v<T, double>) {
return "double:" + std::to_string(x);
} else {
return "string:" + x;
}
}, v);
}
overloadedは複数のoperator()を型ごとに書き分けるやり方でしたが、std::visitに渡せる呼び出し可能オブジェクトは1つのジェネリックラムダでも構いません。xの型は呼ばれるたびにvが実際に保持している型に決まるので、if constexprでTごとの分岐を書けば、実行されないブランチはその型に対してはコンパイルすらされません(普通のifだとどの分岐も全ての型でコンパイルできる必要があり、x + xのようなstd::stringに無い演算があるとエラーになります)。これは参考実装であり、唯一の正解ではありません。