get.hpp

get.hpp #

These are functions for extracting values from toml::value and performing type conversions if necessary.

toml::value can change the type it stores, and toml::get accommodates these types. Technically, all functions use toml::basic_value<TC>. However, for simplicity, we refer to it as toml::value in explanations unless a distinction is necessary. In the documentation, if the template parameter TC changes the type, assume that types like toml::value::integer_type will also change accordingly.

toml::get<T> #

Overview #

Generally, toml::get behaves as follows: You specify T as in toml::get<int>(v).

template<typename T, typename TC>
T get(const basic_value<TC>& v);

However, depending on the type of T, toml::get can exhibit different behaviors.

The types of T can be categorized into:

  1. Types that do not require conversion
  2. Types that require conversion

Detailed conditions and the specific types supported are discussed later.

Types that Do Not Require Conversion #

No conversion is needed if the provided toml::value is already storing the desired type. For instance, since toml::value::integer_type is an alias for std::int64_t, toml::get<std::int64_t>(v) requires no conversion. In this case, toml::get retrieves the integer value from toml::value and returns a reference to it.

If the provided toml::value is a mutable reference (&), the returned value is also a mutable reference (&). If it is an immutable reference (const&), the returned value will also be an immutable reference (const&). Returning a mutable reference allows you to overwrite the value stored in toml::value through that reference.

Types that Require Conversion #

Types other than the ones mentioned above require conversion. For example, since toml::value::integer_type is an alias for std::int64_t, toml::get<std::size_t>(toml::value&) requires conversion. In this case, toml::get retrieves the integer value from toml::value and casts it to return the appropriate type.

toml11 supports not only simple casts but also complex type conversions like converting from toml::array to std::tuple<int, double, std::string>, std::array<double, 4>, or from toml::table to std::map<std::string, int>. For specifics, refer to the subsequent sections.

When Conversion Fails #

Sometimes, the expected type conversion cannot be performed. For example, applying toml::get<int>(v) to a toml::value that holds a table.

In such cases, an attempt to convert to the type most similar to the desired type (in this case, int using as_integer) fails, and a toml::type_error is thrown.

When parsing from a file, an error message similar to the following is output:

terminate called after throwing an instance of 'toml::type_error'
  what():  toml::value::as_integer(): bad_cast to integer
 --> input.toml
   |
 6 | [fruit]
   | ^^^^^^^-- the actual type is table

When T is identical to toml::value #

template<typename T, typename TC>
T& get(basic_value<TC>& v);

template<typename T, typename TC>
T const& get(const basic_value<TC>& v);

template<typename T, typename TC>
T get(basic_value<TC>&& v);

Condition:

  • std::is_same<T, basic_value<TC>> is satisfied.

Since this involves retrieving toml::value from toml::value, no conversion is performed, and the value is returned as is. This exists solely to generalize the implementation of other functions.

This does not fail.

When T is one of toml::value::{some_type} #

template<typename T, typename TC>
T& get(basic_value<TC>& v);

template<typename T, typename TC>
T const& get(const basic_value<TC>& v);

template<typename T, typename TC>
T get(basic_value<TC>&& v);

Condition:

  • T must be the same as one of the types that toml::value can store (e.g., toml::value::boolean_type).

If toml::value is storing a type that matches the specified type in toml::get<T>, such as toml::value::integer_type, no type conversion is needed, and a reference can be returned.

If a different type is stored, a toml::type_error is thrown.

When T is basic_value<OtherTC> with a different TypeConfig #

template<typename T, typename TC>
T get(basic_value<TC>& v);

Condition:

  • T is not toml::basic_value<TC>.
  • T is toml::basic_value<OtherTC>.

When a basic_value that can store different types is specified, conversion is performed.

Since type conversion occurs, the returned value is a new value and not a reference.

This does not fail (except in cases like memory exhaustion).

When T is an integer type #

template<typename T, typename TC>
T get(basic_value<TC>& v);

Condition:

  • std::is_integral<T> is satisfied
  • T is not bool
  • T is not toml::value::integer_type

The function assumes that toml::value holds an integer_type, retrieves its value, converts it to T, and returns it.

If a type other than toml::value::integer_type is stored, a toml::type_error is thrown.

When T is a floating-point type #

template<typename T, typename TC>
T get(basic_value<TC>& v);

Condition:

  • std::is_floating_point<T> is satisfied
  • T is not toml::value::floating_type

The function assumes that toml::value holds a floating_type, retrieves its value, converts it to T, and returns it.

If a type other than toml::value::floating_type is stored, a toml::type_error is thrown.

When T is std::string_view #

This is only available in C++17 and later.

template<typename T, typename TC>
T get(basic_value<TC>& v);

Condition:

  • std::is_same<std::string_view, T> is satisfied

The function assumes that toml::value holds a string_type, retrieves its value, constructs a std::string_view from it, and returns it.

If a type other than toml::value::string_type is stored, a toml::type_error is thrown.

When T is std::chrono::duration #

template<typename T, typename TC>
T get(basic_value<TC>& v);

Condition:

  • T is std::chrono::duration<Rep, Period>

The function assumes that toml::value holds a local_time, retrieves its value, converts it to std::chrono::duration, and returns it.

If a type other than toml::value::local_time is stored, a toml::type_error is thrown.

When T is std::chrono::system_clock::time_point #

template<typename T, typename TC>
T get(basic_value<TC>& v);

Condition:

  • std::is_same<T, std::chrono::system_clock::time_point> is satisfied

If the toml::value holds a local_date, local_datetime, or offset_datetime, this function retrieves the value and converts it to std::chrono::system_clock::time_point, returning the result.

If the value is of a type other than local_date, local_datetime, or offset_datetime, a toml::type_error is thrown.

When T is array-like #

template<typename T, typename TC>
T get(basic_value<TC>& v);

Conditions:

  • T has an iterator
  • T has a value_type
  • T supports push_back(x)
  • T is not toml::value::array_type
  • T is not std::string
  • T is not std::string_view
  • T is not map-like
  • T does not have from_toml() member function
  • toml::from<T> is not defined
  • A constructor from toml::basic_value<TC> is not defined

This includes types like std::vector<int> and std::deque<std::string>.

If the toml::value holds an array, this function retrieves the value and converts it to the specified container type, returning the result.

If the value is of a type other than toml::value::array_type, a toml::type_error is thrown.

When T is std::array #

template<typename T, typename TC>
T get(basic_value<TC>& v);

条件:

  • T is std::array<U, N>

If the toml::value holds an array, this function retrieves the value and converts it to the specified container type, returning the result.

If the value is of a type other than toml::value::array_type, a toml::type_error is thrown.

If the array held by toml::value does not contain enough elements, a std::out_of_range is thrown.

When T is std::forward_list #

template<typename T, typename TC>
T get(basic_value<TC>& v);

Condition:

  • T is std::forward_list<U>

If the toml::value holds an array, this function retrieves the value and converts it to a std::forward_list, returning the result.

If the value is of a type other than toml::value::array_type, a toml::type_error is thrown.

When T is std::pair #

template<typename T, typename TC>
T get(basic_value<TC>& v);

Condition:

  • T is std::pair<T1, T2>

If the toml::value holds an array, this function retrieves the value and converts it to std::pair<T1, T2>, returning the result.

The first and second elements are recursively converted.

If the value is of a type other than basic_value::array_type, a toml::type_error is thrown.

If the array held by toml::value does not contain exactly 2 elements, a std::out_of_range is thrown.

When T is std::tuple #

template<typename T, typename TC>
T get(basic_value<TC>& v);

Condition:

  • T is std::tuple<T1, T2, ... TN>

If the toml::value holds an array, this function retrieves the value and converts it to std::tuple<T1, T2, ...TN>, returning the result.

Each element is recursively converted.

If the value is of a type other than basic_value::array_type, a toml::type_error is thrown.

If the array held by toml::value does not contain exactly std::tuple_size<T>::value elements, a std::out_of_range is thrown.

When T is map-like #

template<typename T, typename TC>
T get(basic_value<TC>& v);

Conditions:

  • T has an iterator
  • T has a key_type
  • T has a value_type
  • T has a mapped_type
  • T is not toml::value::table_type
  • T does not have a from_toml() member function
  • toml::from<T> is not defined
  • A constructor from toml::basic_value<TC> is not defined

This includes types like std::map<std::string, int> and std::unordered_map<std::string, float>.

If the toml::value holds a table, this function retrieves the value and converts it to T, returning the result.

Elements are recursively converted.

If the value is of a type other than basic_value::table_type, a toml::type_error is thrown.

When T is a user-defined type with a specialization of toml::from<T> #

template<typename T, typename TC>
T get(basic_value<TC>& v);

Condition:

  • A specialization of toml::from<T> is defined

If a specialization of toml::from for T is defined, it is used for type conversion.

Ensure this does not conflict with individually supported types (std::array, std::pair, std::tuple etc).

When T is a user-defined type with a from_toml member function #

template<typename T, typename TC>
T get(basic_value<TC>& v);

Conditions:

  • toml::from<T> is not defined
  • T has from_toml() member function

If T has a from_toml(toml::basic_value<TC>) member function, it is used for type conversion.

If toml::from<T> is defined, it takes precedence.

When T is a user-defined type with a constructor that takes toml::basic_value<TC> #

template<typename T, typename TC>
T get(basic_value<TC>& v);

Conditions:

  • toml::from<T> is not defined
  • T does not have from_toml() member function
  • T has a constructor that takes toml::basic_value<TC>

If T has a constructor that takes toml::basic_value<TC>, it is used for type conversion.

If toml::from<T> or T::from_toml is defined, they take precedence.

toml::get_or<T> #

get_or takes a default value for use when the conversion fails, avoiding exceptions.

The default value must be of the same type as the target type T. Therefore, unlike toml::get<T>, T can be inferred in get_or.

When T is basic_value<TC> #

template<typename TC>
basic_value<TC> const& get_or(const basic_value<TC>& v, const basic_value<TC>& opt)

template<typename TC>
basic_value<TC> & get_or(basic_value<TC>& v, basic_value<TC>& opt)

template<typename TC>
basic_value<TC> get_or(basic_value<TC>&& v, basic_value<TC>&& opt)

Since the conversion target is the same toml::value, this never fails.

It exists solely to generalize the implementation of other functions.

When T is basic_value<TC>::{some_type} #

template<typename T, typename TC>
T const& get_or(const basic_value<TC>& v, const T& opt) noexcept

template<typename T, typename TC>
T & get_or(basic_value<TC>& v, T& opt) noexcept

template<typename T, typename TC>     
T get_or(basic_value<TC>&& v, T&& opt) noexcept

Performs the same conversion as toml::get<T>. If it fails, the second argument is returned.

When T is const char* #

template<typename TC>
typename basic_value<TC>::string_type
get_or(const basic_value<TC>& v,
       const typename basic_value<TC>::string_type::value_type* opt);

When const char* is passed, the conversion target is interpreted as std::string.

When T is something else #

template<typename TC>
typename std::remove_cv<typename std::remove_reference<T>::type>::type
get_or(const basic_value<TC>& v, T&& opt);

Performs the same conversion as toml::get<T>. If it fails, the second argument is returned.

Related #