1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
// This file is a part of toml++ and is subject to the the terms of the MIT license.
// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
// 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<int64_t> val{ 3 };
// check lvalue propagates correctly
static_cast<node&>(val).visit(
[](auto&& v) noexcept
{
using val_ref_type = decltype(v);
static_assert(std::is_lvalue_reference_v<val_ref_type>);
using val_type = std::remove_reference_t<val_ref_type>;
static_assert(!std::is_const_v<val_type>);
static_assert(!std::is_volatile_v<val_type>);
});
// check rvalue propagates correctly
static_cast<node&&>(val).visit(
[](auto&& v) noexcept
{
using val_ref_type = decltype(v);
static_assert(std::is_rvalue_reference_v<val_ref_type>);
using val_type = std::remove_reference_t<val_ref_type>;
static_assert(!std::is_const_v<val_type>);
static_assert(!std::is_volatile_v<val_type>);
});
// check const lvalue propagates correctly
static_cast<const node&>(val).visit(
[](auto&& v) noexcept
{
using val_ref_type = decltype(v);
static_assert(std::is_lvalue_reference_v<val_ref_type>);
using val_type = std::remove_reference_t<val_ref_type>;
static_assert(std::is_const_v<val_type>);
static_assert(!std::is_volatile_v<val_type>);
});
// check const rvalue propagates correctly
static_cast<const node&&>(val).visit(
[](auto&& v) noexcept
{
using val_ref_type = decltype(v);
static_assert(std::is_rvalue_reference_v<val_ref_type>);
using val_type = std::remove_reference_t<val_ref_type>;
static_assert(std::is_const_v<val_type>);
static_assert(!std::is_volatile_v<val_type>);
});
// check noexcept
static constexpr auto throwing_visitor = [](auto&&) noexcept(false) {};
static constexpr auto non_throwing_visitor = [](auto&&) noexcept(true) {};
static_assert(!noexcept(static_cast<node&>(val).visit(throwing_visitor)));
static_assert(!noexcept(static_cast<node&&>(val).visit(throwing_visitor)));
static_assert(!noexcept(static_cast<const node&>(val).visit(throwing_visitor)));
static_assert(!noexcept(static_cast<const node&&>(val).visit(throwing_visitor)));
static_assert(noexcept(static_cast<node&>(val).visit(non_throwing_visitor)));
static_assert(noexcept(static_cast<node&&>(val).visit(non_throwing_visitor)));
static_assert(noexcept(static_cast<const node&>(val).visit(non_throwing_visitor)));
static_assert(noexcept(static_cast<const node&&>(val).visit(non_throwing_visitor)));
// check return
static constexpr auto returns_boolean = [](auto& v) noexcept { return toml::is_integer<decltype(v)>; };
auto return_test = static_cast<node&>(val).visit(returns_boolean);
static_assert(std::is_same_v<decltype(return_test), bool>);
CHECK(return_test == true);
}
TEST_CASE("node_view::visit")
{
value<int64_t> val{ 3 };
auto view = node_view{ val };
auto cview = node_view{ std::as_const(val) };
static_assert(!std::is_same_v<decltype(view), decltype(cview)>);
// check mutable views propagate correctly
view.visit(
[](auto&& v) noexcept
{
using val_ref_type = decltype(v);
static_assert(std::is_lvalue_reference_v<val_ref_type>);
using val_type = std::remove_reference_t<val_ref_type>;
static_assert(!std::is_const_v<val_type>);
static_assert(!std::is_volatile_v<val_type>);
});
// check const views propagate correctly
cview.visit(
[](auto&& v) noexcept
{
using val_ref_type = decltype(v);
static_assert(std::is_lvalue_reference_v<val_ref_type>);
using val_type = std::remove_reference_t<val_ref_type>;
static_assert(std::is_const_v<val_type>);
static_assert(!std::is_volatile_v<val_type>);
});
// 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<decltype(v)>; };
auto return_test = view.visit(returns_boolean);
static_assert(std::is_same_v<decltype(return_test), bool>);
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
}
|