libs/parameter/test/preprocessor.cpp
// Copyright Daniel Wallin 2006.
// 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/parameter/preprocessor.hpp>
#include <boost/parameter/binding.hpp>
#include <boost/parameter/config.hpp>
#include "basics.hpp"
#if defined(BOOST_PARAMETER_CAN_USE_MP11)
#include <type_traits>
#else
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_same.hpp>
#endif
namespace test {
BOOST_PARAMETER_BASIC_FUNCTION((int), f, test::tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *)
(index, (int))
)
)
{
typedef typename boost::parameter::binding<
Args,test::tag::index,int&
>::type index_type;
#if defined(BOOST_PARAMETER_CAN_USE_MP11)
static_assert(
std::is_same<index_type,int&>::value
, "index_type == int&"
);
#else
BOOST_MPL_ASSERT((
typename boost::mpl::if_<
boost::is_same<index_type,int&>
, boost::mpl::true_
, boost::mpl::false_
>::type
));
#endif
args[test::_tester](
args[test::_name]
, args[test::_value | 1.f]
, args[test::_index | 2]
);
return 1;
}
} // namespace test
#include <boost/parameter/value_type.hpp>
#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
#include <boost/type_traits/remove_const.hpp>
#endif
namespace test {
BOOST_PARAMETER_BASIC_FUNCTION((int), g, test::tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *)
(index, (int))
)
)
{
typedef typename boost::parameter::value_type<
Args,test::tag::index,int
>::type index_type;
#if defined(BOOST_PARAMETER_CAN_USE_MP11)
static_assert(
std::is_same<
typename std::remove_const<index_type>::type
, int
>::value
, "remove_const<index_type>::type == int"
);
#else
BOOST_MPL_ASSERT((
typename boost::mpl::if_<
boost::is_same<
typename boost::remove_const<index_type>::type
, int
>
, boost::mpl::true_
, boost::mpl::false_
>::type
));
#endif
args[test::_tester](
args[test::_name]
, args[test::_value | 1.f]
, args[test::_index | 2]
);
return 1;
}
} // namespace test
#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
#include <boost/type_traits/remove_reference.hpp>
#endif
namespace test {
BOOST_PARAMETER_FUNCTION((int), h, test::tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *, 1.f)
(index, (int), 2)
)
)
{
#if defined(BOOST_PARAMETER_CAN_USE_MP11)
static_assert(
std::is_same<
typename std::remove_const<
typename std::remove_reference<index_type>::type
>::type
, int
>::value
, "remove_cref<index_type>::type == int"
);
#elif !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \
!BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
BOOST_MPL_ASSERT((
typename boost::mpl::if_<
boost::is_same<
typename boost::remove_const<
typename boost::remove_reference<index_type>::type
>::type
, int
>
, boost::mpl::true_
, boost::mpl::false_
>::type
));
#endif // BOOST_PARAMETER_CAN_USE_MP11 || Borland/MSVC workarounds not needed
tester(name, value, index);
return 1;
}
BOOST_PARAMETER_FUNCTION((int), h2, test::tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *, 1.f)
(index, (int), static_cast<int>(value * 2))
)
)
{
#if defined(BOOST_PARAMETER_CAN_USE_MP11)
static_assert(
std::is_same<
typename std::remove_const<
typename std::remove_reference<index_type>::type
>::type
, int
>::value
, "remove_cref<index_type>::type == int"
);
#elif !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \
!BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
BOOST_MPL_ASSERT((
typename boost::mpl::if_<
boost::is_same<
typename boost::remove_const<
typename boost::remove_reference<index_type>::type
>::type
, int
>
, boost::mpl::true_
, boost::mpl::false_
>::type
));
#endif // BOOST_PARAMETER_CAN_USE_MP11 || Borland/MSVC workarounds not needed
tester(name, value, index);
return 1;
}
} // namespace test
#include <string>
#if !defined(BOOST_NO_SFINAE)
#include <boost/parameter/aux_/preprocessor/nullptr.hpp>
#include <boost/core/enable_if.hpp>
#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/is_convertible.hpp>
#endif
#endif
namespace test {
struct base_0
{
float f;
int i;
template <typename Args>
explicit base_0(
Args const& args
#if !defined(BOOST_NO_SFINAE)
, typename boost::disable_if<
typename boost::mpl::if_<
boost::is_base_of<base_0,Args>
, boost::mpl::true_
, boost::mpl::false_
>::type
>::type* = BOOST_PARAMETER_AUX_PP_NULLPTR
#endif // BOOST_NO_SFINAE
) : f(args[test::_value | 1.f]), i(args[test::_index | 2])
{
}
};
struct class_0 : test::base_0
{
BOOST_PARAMETER_CONSTRUCTOR(class_0, (test::base_0), test::tag,
(optional
(value, *)
(index, *)
)
)
BOOST_PARAMETER_BASIC_FUNCTION_CALL_OPERATOR((int), test::tag,
(optional
(value, *)
(index, *)
)
)
{
this->f = args[test::_value | 2.f];
this->i = args[test::_index | 1];
return 1;
}
};
struct base_1
{
template <typename Args>
explicit base_1(
Args const& args
#if !defined(BOOST_NO_SFINAE)
, typename boost::disable_if<
#if defined(BOOST_PARAMETER_CAN_USE_MP11)
std::is_base_of<base_1,Args>
#else
typename boost::mpl::if_<
boost::is_base_of<base_1,Args>
, boost::mpl::true_
, boost::mpl::false_
>::type
#endif
>::type* = BOOST_PARAMETER_AUX_PP_NULLPTR
#endif // BOOST_NO_SFINAE
)
{
args[test::_tester](
args[test::_name]
, args[test::_value | 1.f]
, args[test::_index | 2]
);
}
};
struct class_1 : test::base_1
{
BOOST_PARAMETER_CONSTRUCTOR(class_1, (test::base_1), test::tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *)
(index, *)
)
)
BOOST_PARAMETER_BASIC_MEMBER_FUNCTION((int), f, test::tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *)
(index, *)
)
)
{
args[test::_tester](
args[test::_name]
, args[test::_value | 1.f]
, args[test::_index | 2]
);
return 1;
}
BOOST_PARAMETER_BASIC_CONST_MEMBER_FUNCTION((int), f, test::tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *)
(index, *)
)
)
{
args[test::_tester](
args[test::_name]
, args[test::_value | 1.f]
, args[test::_index | 2]
);
return 1;
}
BOOST_PARAMETER_MEMBER_FUNCTION((int), f2, test::tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *, 1.f)
(index, *, 2)
)
)
{
tester(name, value, index);
return 1;
}
BOOST_PARAMETER_CONST_MEMBER_FUNCTION((int), f2, test::tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *, 1.f)
(index, *, 2)
)
)
{
tester(name, value, index);
return 1;
}
BOOST_PARAMETER_MEMBER_FUNCTION((int), static f_static, test::tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *, 1.f)
(index, *, 2)
)
)
{
tester(name, value, index);
return 1;
}
BOOST_PARAMETER_FUNCTION_CALL_OPERATOR((int), test::tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *, 1.f)
(index, *, 2)
)
)
{
tester(name, value, index);
return 1;
}
BOOST_PARAMETER_CONST_FUNCTION_CALL_OPERATOR((int), test::tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *, 1.f)
(index, *, 2)
)
)
{
tester(name, value, index);
return 1;
}
};
BOOST_PARAMETER_FUNCTION((int), sfinae, test::tag,
(required
(name, (std::string))
)
)
{
return 1;
}
#if !defined(BOOST_NO_SFINAE)
// On compilers that actually support SFINAE, add another overload
// that is an equally good match and can only be in the overload set
// when the others are not. This tests that the SFINAE is actually
// working. On all other compilers we're just checking that everything
// about SFINAE-enabled code will work, except of course the SFINAE.
template <typename A0>
typename boost::enable_if<
#if defined(BOOST_PARAMETER_CAN_USE_MP11)
std::is_same<int,A0>
#else
typename boost::mpl::if_<
boost::is_same<int,A0>
, boost::mpl::true_
, boost::mpl::false_
>::type
#endif
, int
>::type
sfinae(A0 const& a0)
{
return 0;
}
#endif // BOOST_NO_SFINAE
struct predicate
{
template <typename T, typename Args>
#if defined(BOOST_PARAMETER_CAN_USE_MP11)
using fn = std::is_convertible<T,std::string>;
#else
struct apply
: boost::mpl::if_<
boost::is_convertible<T,std::string>
, boost::mpl::true_
, boost::mpl::false_
>
{
};
#endif
BOOST_PARAMETER_BASIC_CONST_FUNCTION_CALL_OPERATOR((bool), test::tag,
(required
(value, *)
(index, *)
)
)
{
return args[test::_value] < args[test::_index];
}
};
BOOST_PARAMETER_FUNCTION((int), sfinae1, test::tag,
(required
(name, *(test::predicate))
)
)
{
return 1;
}
#if !defined(BOOST_NO_SFINAE)
// On compilers that actually support SFINAE, add another overload
// that is an equally good match and can only be in the overload set
// when the others are not. This tests that the SFINAE is actually
// working. On all other compilers we're just checking that everything
// about SFINAE-enabled code will work, except of course the SFINAE.
template <typename A0>
typename boost::enable_if<
#if defined(BOOST_PARAMETER_CAN_USE_MP11)
std::is_same<int,A0>
#else
typename boost::mpl::if_<
boost::is_same<int,A0>
, boost::mpl::true_
, boost::mpl::false_
>::type
#endif
, int
>::type
sfinae1(A0 const& a0)
{
return 0;
}
#endif // BOOST_NO_SFINAE
struct udt
{
udt(int foo_, int bar_) : foo(foo_), bar(bar_)
{
}
int foo;
int bar;
};
BOOST_PARAMETER_FUNCTION((int), lazy_defaults, test::tag,
(required
(name, *)
)
(optional
(value, *, name.foo)
(index, *, name.bar)
)
)
{
return 0;
}
} // namespace test
#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
#include <boost/parameter/aux_/as_lvalue.hpp>
#endif
#include <boost/core/lightweight_test.hpp>
int main()
{
test::f(
test::values(std::string("foo"), 1.f, 2)
, std::string("foo")
);
test::f(
test::_tester = test::values(std::string("foo"), 1.f, 2)
, test::_name = std::string("foo")
);
int index_lvalue = 2;
test::f(
test::_tester = test::values(std::string("foo"), 1.f, 2)
, test::_name = std::string("foo")
, test::_value = 1.f
, test::_index = index_lvalue
);
test::f(
test::values(std::string("foo"), 1.f, 2)
, std::string("foo")
, 1.f
, index_lvalue
);
test::g(
test::values(std::string("foo"), 1.f, 2)
, std::string("foo")
, 1.f
#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
, boost::parameter::aux::as_lvalue(2)
#else
, 2
#endif
);
test::h(
test::values(std::string("foo"), 1.f, 2)
, std::string("foo")
, 1.f
#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
, boost::parameter::aux::as_lvalue(2)
#else
, 2
#endif
);
test::h2(
test::_tester = test::values(std::string("foo"), 1.f, 2)
, test::_name = std::string("foo")
, test::_value = 1.f
);
test::class_0 u;
BOOST_TEST(2 == u.i);
BOOST_TEST(1.f == u.f);
u();
BOOST_TEST(1 == u.i);
BOOST_TEST(2.f == u.f);
test::class_1 x(
test::values(std::string("foo"), 1.f, 2)
, std::string("foo")
, test::_index = 2
);
x.f(test::values(std::string("foo"), 1.f, 2), std::string("foo"));
x.f(
test::_tester = test::values(std::string("foo"), 1.f, 2)
, test::_name = std::string("foo")
);
x.f2(test::values(std::string("foo"), 1.f, 2), std::string("foo"));
x.f2(
test::_tester = test::values(std::string("foo"), 1.f, 2)
, test::_name = std::string("foo")
);
x(test::values(std::string("foo"), 1.f, 2), std::string("foo"));
x(
test::_tester = test::values(std::string("foo"), 1.f, 2)
, test::_name = std::string("foo")
);
test::class_1 const& x_const = x;
x_const.f(test::values(std::string("foo"), 1.f, 2), std::string("foo"));
x_const.f(
test::_tester = test::values(std::string("foo"), 1.f, 2)
, test::_name = std::string("foo")
);
x_const.f2(test::values(std::string("foo"), 1.f, 2), std::string("foo"));
x_const.f2(
test::_tester = test::values(std::string("foo"), 1.f, 2)
, test::_name = std::string("foo")
);
test::class_1::f_static(
test::values(std::string("foo"), 1.f, 2)
, std::string("foo")
);
test::class_1::f_static(
test::_tester = test::values(std::string("foo"), 1.f, 2)
, test::_name = std::string("foo")
);
x_const(test::values(std::string("foo"), 1.f, 2), std::string("foo"));
x_const(
test::_tester = test::values(std::string("foo"), 1.f, 2)
, test::_name = std::string("foo")
);
test::predicate p;
test::predicate const& p_const = p;
BOOST_TEST(p_const(3, 4));
BOOST_TEST(!p_const(4, 3));
BOOST_TEST(!p_const(test::_index = 3, test::_value = 4));
#if !defined(BOOST_NO_SFINAE) && \
!BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
// GCC 3- tries to bind string literals
// to non-const references to char const*.
// BOOST_TEST(test::sfinae("foo") == 1);
char const* foo_str = "foo";
BOOST_TEST(test::sfinae(foo_str) == 1);
BOOST_TEST(test::sfinae(1) == 0);
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580))
// Sun actually eliminates the desired overload for some reason.
// Disabling this part of the test because SFINAE abilities are
// not the point of this test.
BOOST_TEST(test::sfinae1(foo_str) == 1);
#endif
BOOST_TEST(test::sfinae1(1) == 0);
#endif
test::lazy_defaults(test::_name = test::udt(0, 1));
test::lazy_defaults(test::_name = 0, test::_value = 1, test::_index = 2);
return boost::report_errors();
}