// This file is a part of toml++ and is subject to the the terms of the MIT license. // Copyright (c) Mark Gillard // See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. // SPDX-License-Identifier: MIT #include "tests.h" TOML_DISABLE_SPAM_WARNINGS; TEST_CASE("node::visit") { value val{ 3 }; // check lvalue propagates correctly static_cast(val).visit( [](auto&& v) noexcept { using val_ref_type = decltype(v); static_assert(std::is_lvalue_reference_v); using val_type = std::remove_reference_t; static_assert(!std::is_const_v); static_assert(!std::is_volatile_v); }); // check rvalue propagates correctly static_cast(val).visit( [](auto&& v) noexcept { using val_ref_type = decltype(v); static_assert(std::is_rvalue_reference_v); using val_type = std::remove_reference_t; static_assert(!std::is_const_v); static_assert(!std::is_volatile_v); }); // check const lvalue propagates correctly static_cast(val).visit( [](auto&& v) noexcept { using val_ref_type = decltype(v); static_assert(std::is_lvalue_reference_v); using val_type = std::remove_reference_t; static_assert(std::is_const_v); static_assert(!std::is_volatile_v); }); // check const rvalue propagates correctly static_cast(val).visit( [](auto&& v) noexcept { using val_ref_type = decltype(v); static_assert(std::is_rvalue_reference_v); using val_type = std::remove_reference_t; static_assert(std::is_const_v); static_assert(!std::is_volatile_v); }); // check noexcept static constexpr auto throwing_visitor = [](auto&&) noexcept(false) {}; static constexpr auto non_throwing_visitor = [](auto&&) noexcept(true) {}; static_assert(!noexcept(static_cast(val).visit(throwing_visitor))); static_assert(!noexcept(static_cast(val).visit(throwing_visitor))); static_assert(!noexcept(static_cast(val).visit(throwing_visitor))); static_assert(!noexcept(static_cast(val).visit(throwing_visitor))); static_assert(noexcept(static_cast(val).visit(non_throwing_visitor))); static_assert(noexcept(static_cast(val).visit(non_throwing_visitor))); static_assert(noexcept(static_cast(val).visit(non_throwing_visitor))); static_assert(noexcept(static_cast(val).visit(non_throwing_visitor))); // check return static constexpr auto returns_boolean = [](auto& v) noexcept { return toml::is_integer; }; auto return_test = static_cast(val).visit(returns_boolean); static_assert(std::is_same_v); CHECK(return_test == true); } TEST_CASE("node_view::visit") { value val{ 3 }; auto view = node_view{ val }; auto cview = node_view{ std::as_const(val) }; static_assert(!std::is_same_v); // check mutable views propagate correctly view.visit( [](auto&& v) noexcept { using val_ref_type = decltype(v); static_assert(std::is_lvalue_reference_v); using val_type = std::remove_reference_t; static_assert(!std::is_const_v); static_assert(!std::is_volatile_v); }); // check const views propagate correctly cview.visit( [](auto&& v) noexcept { using val_ref_type = decltype(v); static_assert(std::is_lvalue_reference_v); using val_type = std::remove_reference_t; static_assert(std::is_const_v); static_assert(!std::is_volatile_v); }); // check noexcept static constexpr auto throwing_visitor = [](auto&&) noexcept(false) {}; static constexpr auto non_throwing_visitor = [](auto&&) noexcept(true) {}; static_assert(!noexcept(view.visit(throwing_visitor))); static_assert(!noexcept(cview.visit(throwing_visitor))); static_assert(noexcept(view.visit(non_throwing_visitor))); static_assert(noexcept(cview.visit(non_throwing_visitor))); // check return static constexpr auto returns_boolean = [](auto&& v) noexcept { return toml::is_integer; }; auto return_test = view.visit(returns_boolean); static_assert(std::is_same_v); CHECK(return_test == true); // check that null views don't invoke the visitor // clang-format off auto null_view = decltype(view){}; auto null_cview = decltype(cview){}; unsigned count{}; unsigned mask{}; view.visit([&](auto&&) noexcept { count++; mask |= 0b0001u; }); cview.visit([&](auto&&) noexcept { count++; mask |= 0b0010u; }); null_view.visit([&](auto&&) noexcept { count++; mask |= 0b0100u; }); null_cview.visit([&](auto&&) noexcept { count++; mask |= 0b1000u; }); CHECK(count == 2u); CHECK(mask == 0b0011u); // clang-format on }