Skip to content

Commit

Permalink
Clarify type restrictions of get_value() & get_value_ref() APIs (#424)
Browse files Browse the repository at this point in the history
* emit static_assertion errors on get_value() calls with reference, pointer and C-style array types

* clarify type restrictions of get_value() and get_value_ref() APIs

* run amalgamation
  • Loading branch information
fktn-k authored Nov 16, 2024
1 parent f121341 commit cf79a86
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 9 deletions.
3 changes: 2 additions & 1 deletion docs/mkdocs/docs/api/basic_node/get_value.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ This function converts a [fkyaml::basic_node](./index.md) to either
ConverterType<ValueType>::from_node(*this, ret);
return ret;
```
This library implements conversions from a node to a number of STL container types and scalar types. (see the notes down below)
This library implements conversions from a node to a number of STL container types and scalar types. (see the notes down below)
Note that ValueType cannot be either a reference, pointer or C-style array type except `std::nullptr_t`.
2. a [fkyaml::basic_node](./index.md) object
The function is equivalent to executing
```cpp
Expand Down
3 changes: 1 addition & 2 deletions docs/mkdocs/docs/api/basic_node/get_value_ref.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ This API makes no copies.
***ReferenceType***
: reference type to the target YAML node value.
This must be a reference to [`sequence_type`](sequence_type.md), [`mapping_type`](mapping_type.md), [`boolean_type`](boolean_type.md), [`integer_type`](integer_type.md), [`float_number_type`](float_number_type.md) or [`string_type`](string_type.md).
The above restriction is enforced by a static assertion.
This must be a (const) reference type to [`sequence_type`](sequence_type.md), [`mapping_type`](mapping_type.md), [`boolean_type`](boolean_type.md), [`integer_type`](integer_type.md), [`float_number_type`](float_number_type.md) or [`string_type`](string_type.md).
## **Return Value**
Expand Down
13 changes: 10 additions & 3 deletions include/fkYAML/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1305,15 +1305,22 @@ class basic_node {

/// @brief Get the node value object converted into a given type.
/// @note This function requires T objects to be default constructible.
/// @tparam T A compatible value type which might be cv-qualified or a reference type.
/// @tparam ValueType A compatible value type, without cv-qualifiers and reference by default.
/// @tparam T A compatible value type which might be cv-qualified.
/// @tparam ValueType A compatible value type with cv-qualifiers removed by default.
/// @return A compatible native data value converted from the basic_node object.
/// @sa https://fktn-k.github.io/fkYAML/api/basic_node/get_value/
template <
typename T, typename ValueType = detail::remove_cvref_t<T>,
typename T, typename ValueType = detail::remove_cv_t<T>,
detail::enable_if_t<std::is_default_constructible<ValueType>::value, int> = 0>
T get_value() const noexcept(
noexcept(std::declval<const basic_node>().template get_value_impl<ValueType>(std::declval<ValueType&>()))) {
// emit a compile error if T is either a reference, pointer or C-style array type.
static_assert(
!std::is_reference<T>::value,
"get_value() cannot be called with reference types. you might want to call get_value_ref().");
static_assert(!std::is_pointer<T>::value, "get_value() cannot be called with pointer types.");
static_assert(!std::is_array<T>::value, "get_value() cannot be called with C-style array types.");

auto ret = ValueType();
if (has_anchor_name()) {
auto itr = mp_meta->anchor_table.equal_range(m_prop.anchor).first;
Expand Down
13 changes: 10 additions & 3 deletions single_include/fkYAML/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12972,15 +12972,22 @@ class basic_node {

/// @brief Get the node value object converted into a given type.
/// @note This function requires T objects to be default constructible.
/// @tparam T A compatible value type which might be cv-qualified or a reference type.
/// @tparam ValueType A compatible value type, without cv-qualifiers and reference by default.
/// @tparam T A compatible value type which might be cv-qualified.
/// @tparam ValueType A compatible value type with cv-qualifiers removed by default.
/// @return A compatible native data value converted from the basic_node object.
/// @sa https://fktn-k.github.io/fkYAML/api/basic_node/get_value/
template <
typename T, typename ValueType = detail::remove_cvref_t<T>,
typename T, typename ValueType = detail::remove_cv_t<T>,
detail::enable_if_t<std::is_default_constructible<ValueType>::value, int> = 0>
T get_value() const noexcept(
noexcept(std::declval<const basic_node>().template get_value_impl<ValueType>(std::declval<ValueType&>()))) {
// emit a compile error if T is either a reference, pointer or C-style array type.
static_assert(
!std::is_reference<T>::value,
"get_value() cannot be called with reference types. you might want to call get_value_ref().");
static_assert(!std::is_pointer<T>::value, "get_value() cannot be called with pointer types.");
static_assert(!std::is_array<T>::value, "get_value() cannot be called with C-style array types.");

auto ret = ValueType();
if (has_anchor_name()) {
auto itr = mp_meta->anchor_table.equal_range(m_prop.anchor).first;
Expand Down
9 changes: 9 additions & 0 deletions test/unit_test/test_node_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2373,6 +2373,9 @@ struct string_wrap {
std::string str;
};

template <typename T, typename U>
using get_fn_t = decltype(std::declval<T>().template get<U>());

TEST_CASE("Node_GetValue") {

SECTION("sequence") {
Expand Down Expand Up @@ -2966,6 +2969,12 @@ TEST_CASE("Node_GetValue") {
REQUIRE_FALSE(opt_bool.has_value());
}
#endif

SECTION("unsupported types") {
STATIC_REQUIRE_FALSE(fkyaml::detail::is_detected<get_fn_t, const fkyaml::node&, int*>::value);
STATIC_REQUIRE_FALSE(fkyaml::detail::is_detected<get_fn_t, const fkyaml::node&, int[]>::value);
STATIC_REQUIRE_FALSE(fkyaml::detail::is_detected<get_fn_t, const fkyaml::node&, int&>::value);
}
}

//
Expand Down

0 comments on commit cf79a86

Please sign in to comment.