userver: userver/formats/parse/boost_variant.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
boost_variant.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/formats/parse/boost_variant.hpp
4/// @brief Ineffective but generic parser for boost::variant type
5///
6/// Parsing is performed for each of the N alternatives in variant, N-1
7/// exceptions is thrown and caught during the parsing.
8///
9/// @ingroup userver_universal userver_formats_parse
10
11#include <boost/variant/variant.hpp>
12
13#include <userver/compiler/demangle.hpp>
14#include <userver/formats/parse/variant.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace formats::parse {
19
20namespace impl {
21template <class T, class Value, typename Result>
22void ParseBoostVariantSingle(const Value& value,
23 std::optional<Result>& result) {
24 if (result) {
25 std::type_index old_type = result->type();
26 try {
27 value.template As<T>();
28 } catch (const std::exception&) {
29 return;
30 }
31
32 ThrowVariantAmbiguousParse<typename Value::ParseException, Result, T>(
33 value.GetPath(), old_type);
34 } else {
35 // No result yet
36 try {
37 result = value.template As<T>();
38 } catch (const std::exception&) {
39 }
40 }
41}
42
43} // namespace impl
44
45template <class Value, typename... Types>
46boost::variant<Types...> Parse(const Value& value,
47 formats::parse::To<boost::variant<Types...>>) {
48 std::optional<boost::variant<Types...>> result;
49 (impl::ParseBoostVariantSingle<Types>(value, result), ...);
50
51 if (!result) {
52 ThrowVariantParseException<typename Value::ParseException,
53 boost::variant<Types...>>(value.GetPath());
54 }
55
56 return std::move(*result);
57}
58
59} // namespace formats::parse
60
61USERVER_NAMESPACE_END