/*============================================================================= Copyright (c) 2017 Paul Fultz II proj.cpp 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 #include #include #include "test.hpp" #include struct foo { constexpr foo(int xp) : x(xp) {} int x; }; struct select_x { template constexpr auto operator()(T&& x) const BOOST_HOF_RETURNS(x.x); }; BOOST_HOF_TEST_CASE() { #ifndef _MSC_VER constexpr #endif auto add = boost::hof::_ + boost::hof::_; BOOST_HOF_STATIC_TEST_CHECK(boost::hof::proj(select_x(), add)(foo(1), foo(2)) == 3); // Using mutable_ as a workaround on libc++, since mem_fn does not meet the // requirements of a FunctionObject BOOST_HOF_TEST_CHECK(boost::hof::proj(boost::hof::mutable_(std::mem_fn(&foo::x)), add)(foo(1), foo(2)) == 3); static_assert(boost::hof::detail::is_default_constructible::value, "Not default constructible"); } BOOST_HOF_TEST_CASE() { #ifndef _MSC_VER constexpr #endif auto add = boost::hof::_ + boost::hof::_; BOOST_HOF_STATIC_TEST_CHECK(boost::hof::proj(select_x(), add)(foo(1), foo(2)) == 3); BOOST_HOF_TEST_CHECK(boost::hof::proj(&foo::x, add)(foo(1), foo(2)) == 3); static_assert(boost::hof::detail::is_default_constructible::value, "Not default constructible"); } BOOST_HOF_TEST_CASE() { auto indirect_add = boost::hof::proj(*boost::hof::_, boost::hof::_ + boost::hof::_); BOOST_HOF_TEST_CHECK(indirect_add(std::unique_ptr(new int(1)), std::unique_ptr(new int(2))) == 3); static_assert(boost::hof::detail::is_default_constructible::value, "Not default constructible"); } struct select_x_1 { std::unique_ptr i; select_x_1() : i(new int(2)) {} template auto operator()(T&& x) const BOOST_HOF_RETURNS(x.x * (*i)); }; struct sum_1 { std::unique_ptr i; sum_1() : i(new int(1)) {} template auto operator()(T&& x, U&& y) const BOOST_HOF_RETURNS(x + y + *i); }; BOOST_HOF_TEST_CASE() { BOOST_HOF_TEST_CHECK(boost::hof::proj(select_x_1(), sum_1())(foo(1), foo(2)) == 7); } BOOST_HOF_TEST_CASE() { std::string s; auto f = [&](const std::string& x) { s += x; }; boost::hof::proj(f)("hello", "-", "world"); BOOST_HOF_TEST_CHECK(s == "hello-world"); boost::hof::proj(f)(); BOOST_HOF_TEST_CHECK(s == "hello-world"); } BOOST_HOF_TEST_CASE() { std::string s; auto f = [&](const std::string& x) { s += x; return s; }; auto last = [](const std::string& x, const std::string& y, const std::string& z) { BOOST_HOF_TEST_CHECK(x == "hello"); BOOST_HOF_TEST_CHECK(y == "hello-"); BOOST_HOF_TEST_CHECK(z == "hello-world"); return z; }; BOOST_HOF_TEST_CHECK(boost::hof::proj(f, last)("hello", "-", "world") == "hello-world"); } template struct bool_ { static const bool value = B; }; struct constexpr_check { template constexpr int operator()(T) const { static_assert(T::value, "Failed"); return 0; } }; struct constexpr_check_each { template constexpr bool operator()(T x) const { return boost::hof::proj(constexpr_check())(x, x), true; } }; BOOST_HOF_TEST_CASE() { BOOST_HOF_STATIC_TEST_CHECK(constexpr_check_each()(bool_())); } BOOST_HOF_TEST_CASE() { boost::hof::proj(boost::hof::identity, boost::hof::identity)(0); } struct bar {}; BOOST_HOF_TEST_CASE() { auto f = boost::hof::proj(bar{}); static_assert(!boost::hof::is_invocable::value, "Not sfinae friendly"); static_assert(!boost::hof::is_invocable::value, "Not sfinae friendly"); static_assert(!boost::hof::is_invocable::value, "Not sfinae friendly"); } BOOST_HOF_TEST_CASE() { auto f = boost::hof::proj(bar{}, bar{}); static_assert(!boost::hof::is_invocable::value, "Not sfinae friendly"); static_assert(!boost::hof::is_invocable::value, "Not sfinae friendly"); static_assert(!boost::hof::is_invocable::value, "Not sfinae friendly"); static_assert(!boost::hof::is_invocable::value, "Not sfinae friendly"); }