summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/yap/test/print.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/yap/test/print.cpp')
-rw-r--r--src/boost/libs/yap/test/print.cpp1595
1 files changed, 1595 insertions, 0 deletions
diff --git a/src/boost/libs/yap/test/print.cpp b/src/boost/libs/yap/test/print.cpp
new file mode 100644
index 00000000..106dcea4
--- /dev/null
+++ b/src/boost/libs/yap/test/print.cpp
@@ -0,0 +1,1595 @@
+// Copyright (C) 2016-2018 T. Zachary Laine
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#include <boost/yap/expression.hpp>
+#include <boost/yap/print.hpp>
+
+#include <boost/test/minimal.hpp>
+
+#include <sstream>
+#include <regex>
+
+
+template<typename T>
+using term = boost::yap::terminal<boost::yap::expression, T>;
+
+template<typename T>
+using ref = boost::yap::expression_ref<boost::yap::expression, T>;
+
+namespace yap = boost::yap;
+namespace bh = boost::hana;
+
+
+template<boost::yap::expr_kind Kind, typename Tuple>
+struct user_expr
+{
+ static boost::yap::expr_kind const kind = Kind;
+
+ Tuple elements;
+};
+
+BOOST_YAP_USER_BINARY_OPERATOR(plus, user_expr, user_expr)
+
+template<typename T>
+using user_term = boost::yap::terminal<user_expr, T>;
+
+template<typename T>
+using user_ref = boost::yap::expression_ref<user_expr, T>;
+
+struct thing
+{};
+
+std::string fix_tti(std::string s)
+{
+ // msvc: remove struct/class prefixes
+ static const std::regex estruct("(struct|class) ");
+ s = std::regex_replace(s, estruct, "");
+
+ // gcc/clang: strip integral literals suffixes
+ static const std::regex eint("(\\d)u?l{0,2}");
+ s = std::regex_replace(s, eint, "$1");
+
+ return s;
+}
+
+int test_main(int, char * [])
+{
+ {
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::terminal) == std::string("term"));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::unary_plus) == std::string("+"));
+ BOOST_CHECK(yap::op_string(yap::expr_kind::negate) == std::string("-"));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::dereference) == std::string("*"));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::complement) == std::string("~"));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::address_of) == std::string("&"));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::logical_not) == std::string("!"));
+
+ BOOST_CHECK(yap::op_string(yap::expr_kind::pre_inc) == std::string("++"));
+ BOOST_CHECK(yap::op_string(yap::expr_kind::pre_dec) == std::string("--"));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::post_inc) == std::string("++(int)"));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::post_dec) == std::string("--(int)"));
+
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::shift_left) == std::string("<<"));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::shift_right) == std::string(">>"));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::multiplies) == std::string("*"));
+ BOOST_CHECK(yap::op_string(yap::expr_kind::divides) == std::string("/"));
+ BOOST_CHECK(yap::op_string(yap::expr_kind::modulus) == std::string("%"));
+
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::multiplies_assign) ==
+ std::string("*="));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::divides_assign) ==
+ std::string("/="));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::modulus_assign) ==
+ std::string("%="));
+
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::plus_assign) == std::string("+="));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::minus_assign) == std::string("-="));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::bitwise_and_assign) ==
+ std::string("&="));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::bitwise_or_assign) ==
+ std::string("|="));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::bitwise_xor_assign) ==
+ std::string("^="));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind::subscript) == std::string("[]"));
+ BOOST_CHECK(yap::op_string(yap::expr_kind::if_else) == std::string("?:"));
+ BOOST_CHECK(yap::op_string(yap::expr_kind::call) == std::string("()"));
+ BOOST_CHECK(
+ yap::op_string(yap::expr_kind(-1)) ==
+ std::string("** ERROR: UNKNOWN OPERATOR! **"));
+ }
+
+ {
+ user_term<double> unity{1.0};
+ int i_ = 42;
+ user_term<int &&> i{std::move(i_)};
+ user_expr<
+ yap::expr_kind::plus,
+ bh::tuple<user_ref<user_term<double> &>, user_term<int &&>>>
+ expr = unity + std::move(i);
+ user_expr<
+ yap::expr_kind::plus,
+ bh::tuple<
+ user_ref<user_term<double> &>,
+ user_expr<
+ yap::expr_kind::plus,
+ bh::tuple<
+ user_ref<user_term<double> &>,
+ user_term<int &&>>>>>
+ unevaluated_expr = unity + std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<+>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<+>
+ term<double>[=1] &
+ expr<+>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ user_term<thing> a_thing{bh::make_tuple(thing{})};
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ user_term<double> const const_unity{1.0};
+ user_expr<
+ yap::expr_kind::plus,
+ bh::tuple<
+ user_ref<user_term<double> &>,
+ user_ref<user_term<double> const &>>>
+ nonconst_plus_const = unity + const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_plus_const);
+ BOOST_CHECK(oss.str() == R"(expr<+>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ auto nonconst_plus_nonconst_plus_const = unity + nonconst_plus_const;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_plus_nonconst_plus_const);
+ BOOST_CHECK(oss.str() == R"(expr<+>
+ term<double>[=1] &
+ expr<+> &
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ auto const const_nonconst_plus_const = nonconst_plus_const;
+ auto nonconst_plus_nonconst_plus_const_2 =
+ unity + const_nonconst_plus_const;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_plus_nonconst_plus_const_2);
+ BOOST_CHECK(oss.str() == R"(expr<+>
+ term<double>[=1] &
+ expr<+> const &
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::plus,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity + std::move(i);
+ yap::expression<
+ yap::expr_kind::plus,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::plus,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity + std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<+>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<+>
+ term<double>[=1] &
+ expr<+>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::plus,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_plus_const = unity + const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_plus_const);
+ BOOST_CHECK(oss.str() == R"(expr<+>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::minus,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity - std::move(i);
+ yap::expression<
+ yap::expr_kind::minus,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::minus,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity - std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<->
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<->
+ term<double>[=1] &
+ expr<->
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::minus,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_minus_const = unity - const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_minus_const);
+ BOOST_CHECK(oss.str() == R"(expr<->
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::less,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity < std::move(i);
+ yap::expression<
+ yap::expr_kind::less,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::less,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity < std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<<>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<<>
+ term<double>[=1] &
+ expr<<>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::less,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_less_const = unity < const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_less_const);
+ BOOST_CHECK(oss.str() == R"(expr<<>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::greater,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity > std::move(i);
+ yap::expression<
+ yap::expr_kind::greater,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::greater,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity > std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<>>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<>>
+ term<double>[=1] &
+ expr<>>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::greater,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_greater_const = unity > const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_greater_const);
+ BOOST_CHECK(oss.str() == R"(expr<>>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::less_equal,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity <= std::move(i);
+ yap::expression<
+ yap::expr_kind::less_equal,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::less_equal,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity <= std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<<=>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<<=>
+ term<double>[=1] &
+ expr<<=>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::less_equal,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_less_equal_const = unity <= const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_less_equal_const);
+ BOOST_CHECK(oss.str() == R"(expr<<=>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::greater_equal,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity >= std::move(i);
+ yap::expression<
+ yap::expr_kind::greater_equal,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::greater_equal,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity >= std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<>=>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<>=>
+ term<double>[=1] &
+ expr<>=>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::greater_equal,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_greater_equal_const = unity >= const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_greater_equal_const);
+ BOOST_CHECK(oss.str() == R"(expr<>=>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::equal_to,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity == std::move(i);
+ yap::expression<
+ yap::expr_kind::equal_to,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::equal_to,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity == std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<==>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<==>
+ term<double>[=1] &
+ expr<==>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::equal_to,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_equal_to_const = unity == const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_equal_to_const);
+ BOOST_CHECK(oss.str() == R"(expr<==>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::not_equal_to,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity != std::move(i);
+ yap::expression<
+ yap::expr_kind::not_equal_to,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::not_equal_to,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity != std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<!=>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<!=>
+ term<double>[=1] &
+ expr<!=>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::not_equal_to,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_not_equal_to_const = unity != const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_not_equal_to_const);
+ BOOST_CHECK(oss.str() == R"(expr<!=>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::logical_or,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity || std::move(i);
+ yap::expression<
+ yap::expr_kind::logical_or,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::logical_or,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity || std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<||>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<||>
+ term<double>[=1] &
+ expr<||>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::logical_or,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_logical_or_const = unity || const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_logical_or_const);
+ BOOST_CHECK(oss.str() == R"(expr<||>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::logical_and,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity && std::move(i);
+ yap::expression<
+ yap::expr_kind::logical_and,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::logical_and,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity && std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<&&>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<&&>
+ term<double>[=1] &
+ expr<&&>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::logical_and,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_logical_and_const = unity && const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_logical_and_const);
+ BOOST_CHECK(oss.str() == R"(expr<&&>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::bitwise_and,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity & std::move(i);
+ yap::expression<
+ yap::expr_kind::bitwise_and,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::bitwise_and,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity & std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<&>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<&>
+ term<double>[=1] &
+ expr<&>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::bitwise_and,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_bitwise_and_const = unity & const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_bitwise_and_const);
+ BOOST_CHECK(oss.str() == R"(expr<&>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::bitwise_or,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity | std::move(i);
+ yap::expression<
+ yap::expr_kind::bitwise_or,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::bitwise_or,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity | std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<|>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<|>
+ term<double>[=1] &
+ expr<|>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::bitwise_or,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_bitwise_or_const = unity | const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_bitwise_or_const);
+ BOOST_CHECK(oss.str() == R"(expr<|>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::bitwise_xor,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity ^ std::move(i);
+ yap::expression<
+ yap::expr_kind::bitwise_xor,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::bitwise_xor,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity ^ std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<^>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<^>
+ term<double>[=1] &
+ expr<^>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::bitwise_xor,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_bitwise_xor_const = unity ^ const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_bitwise_xor_const);
+ BOOST_CHECK(oss.str() == R"(expr<^>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::comma,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = (unity, std::move(i));
+ yap::expression<
+ yap::expr_kind::comma,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::comma,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = (unity, std::move(expr));
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<,>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<,>
+ term<double>[=1] &
+ expr<,>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::comma,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_comma_const = (unity, const_unity);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_comma_const);
+ BOOST_CHECK(oss.str() == R"(expr<,>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::mem_ptr,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity->*std::move(i);
+ yap::expression<
+ yap::expr_kind::mem_ptr,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::mem_ptr,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity->*std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<->*>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<->*>
+ term<double>[=1] &
+ expr<->*>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::mem_ptr,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_mem_ptr_const = unity->*const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_mem_ptr_const);
+ BOOST_CHECK(oss.str() == R"(expr<->*>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::assign,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity = std::move(i);
+ yap::expression<
+ yap::expr_kind::assign,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::assign,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity = std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<=>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<=>
+ term<double>[=1] &
+ expr<=>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::shift_left_assign,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity <<= std::move(i);
+ yap::expression<
+ yap::expr_kind::shift_left_assign,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::shift_left_assign,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity <<= std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<<<=>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<<<=>
+ term<double>[=1] &
+ expr<<<=>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::shift_left_assign,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_shift_left_assign_const = unity <<= const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_shift_left_assign_const);
+ BOOST_CHECK(oss.str() == R"(expr<<<=>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ {
+ term<double> unity{1.0};
+ int i_ = 42;
+ term<int &&> i{std::move(i_)};
+ yap::expression<
+ yap::expr_kind::shift_right_assign,
+ bh::tuple<ref<term<double> &>, term<int &&>>>
+ expr = unity >>= std::move(i);
+ yap::expression<
+ yap::expr_kind::shift_right_assign,
+ bh::tuple<
+ ref<term<double> &>,
+ yap::expression<
+ yap::expr_kind::shift_right_assign,
+ bh::tuple<ref<term<double> &>, term<int &&>>>>>
+ unevaluated_expr = unity >>= std::move(expr);
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unity);
+ BOOST_CHECK(oss.str() == R"(term<double>[=1]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, expr);
+ BOOST_CHECK(oss.str() == R"(expr<>>=>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, unevaluated_expr);
+ BOOST_CHECK(oss.str() == R"(expr<>>=>
+ term<double>[=1] &
+ expr<>>=>
+ term<double>[=1] &
+ term<int &&>[=42]
+)");
+ }
+
+ term<thing> a_thing(thing{});
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, a_thing);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<thing>[=<<unprintable-value>>]
+)");
+ }
+
+ term<double> const const_unity{1.0};
+ yap::expression<
+ yap::expr_kind::shift_right_assign,
+ bh::tuple<ref<term<double> &>, ref<term<double> const &>>>
+ nonconst_shift_right_assign_const = unity >>= const_unity;
+
+ {
+ std::ostringstream oss;
+ yap::print(oss, nonconst_shift_right_assign_const);
+ BOOST_CHECK(oss.str() == R"(expr<>>=>
+ term<double>[=1] &
+ term<double>[=1] const &
+)");
+ }
+
+ {
+ using namespace yap::literals;
+ std::ostringstream oss;
+ yap::print(oss, 1_p);
+ BOOST_CHECK(fix_tti(oss.str()) == R"(term<boost::yap::placeholder<1>>[=1]
+)");
+ }
+ }
+
+ return 0;
+}