blob: 792a1b72c88616fcdb9682e926c78631b4b76c17 [file] [log] [blame]
// Copyright Daniel Wallin 2006. Use, modification and distribution is
// subject to 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/keyword.hpp>
#include <boost/type_traits/is_const.hpp>
#include <string>
#include "basics.hpp"
#ifndef BOOST_NO_SFINAE
# include <boost/utility/enable_if.hpp>
#endif
namespace test {
BOOST_PARAMETER_BASIC_FUNCTION((int), f, tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *)
(out(index), (int))
)
)
{
typedef typename boost::parameter::binding<
Args, tag::index, int&
>::type index_type;
BOOST_MPL_ASSERT((boost::is_same<index_type, int&>));
args[tester](
args[name]
, args[value | 1.f]
, args[index | 2]
);
return 1;
}
BOOST_PARAMETER_BASIC_FUNCTION((int), g, tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *)
(out(index), (int))
)
)
{
typedef typename boost::parameter::binding<
Args, tag::index, int const&
>::type index_type;
BOOST_MPL_ASSERT((boost::is_same<index_type, int const&>));
args[tester](
args[name]
, args[value | 1.f]
, args[index | 2]
);
return 1;
}
BOOST_PARAMETER_FUNCTION((int), h, tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *, 1.f)
(out(index), (int), 2)
)
)
{
# if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) \
&& !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
BOOST_MPL_ASSERT((boost::is_same<index_type, int>));
# endif
tester(
name
, value
, index
);
return 1;
}
BOOST_PARAMETER_FUNCTION((int), h2, tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *, 1.f)
(out(index), (int), (int)value * 2)
)
)
{
# if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) \
&& !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
BOOST_MPL_ASSERT((boost::is_same<index_type, int>));
# endif
tester(
name
, value
, index
);
return 1;
}
struct base
{
template <class Args>
base(Args const& args)
{
args[tester](
args[name]
, args[value | 1.f]
, args[index | 2]
);
}
};
struct class_ : base
{
BOOST_PARAMETER_CONSTRUCTOR(class_, (base), tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *)
(index, *)
)
)
BOOST_PARAMETER_BASIC_MEMBER_FUNCTION((int), f, tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *)
(index, *)
)
)
{
args[tester](
args[name]
, args[value | 1.f]
, args[index | 2]
);
return 1;
}
BOOST_PARAMETER_BASIC_CONST_MEMBER_FUNCTION((int), f, tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *)
(index, *)
)
)
{
args[tester](
args[name]
, args[value | 1.f]
, args[index | 2]
);
return 1;
}
BOOST_PARAMETER_MEMBER_FUNCTION((int), f2, tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *, 1.f)
(index, *, 2)
)
)
{
tester(name, value, index);
return 1;
}
BOOST_PARAMETER_CONST_MEMBER_FUNCTION((int), f2, tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *, 1.f)
(index, *, 2)
)
)
{
tester(name, value, index);
return 1;
}
BOOST_PARAMETER_MEMBER_FUNCTION((int), static f_static, tag,
(required
(tester, *)
(name, *)
)
(optional
(value, *, 1.f)
(index, *, 2)
)
)
{
tester(name, value, index);
return 1;
}
};
BOOST_PARAMETER_FUNCTION(
(int), sfinae, tag,
(required
(name, (std::string))
)
)
{
return 1;
}
#ifndef 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<class A0>
typename boost::enable_if<boost::is_same<int,A0>, int>::type
sfinae(A0 const& a0)
{
return 0;
}
#endif
#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580))
// Sun has problems with this syntax:
//
// template1< r* ( template2<x> ) >
//
// Workaround: factor template2<x> into a separate typedef
typedef boost::is_convertible<boost::mpl::_, std::string> predicate;
BOOST_PARAMETER_FUNCTION(
(int), sfinae1, tag,
(required
(name, *(predicate))
)
)
{
return 1;
}
#else
BOOST_PARAMETER_FUNCTION(
(int), sfinae1, tag,
(required
(name, *(boost::is_convertible<boost::mpl::_, std::string>))
)
)
{
return 1;
}
#endif
#ifndef 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<class A0>
typename boost::enable_if<boost::is_same<int,A0>, int>::type
sfinae1(A0 const& a0)
{
return 0;
}
#endif
template <class T>
T const& as_lvalue(T const& x)
{
return x;
}
struct udt
{
udt(int foo, int bar)
: foo(foo)
, bar(bar)
{}
int foo;
int bar;
};
BOOST_PARAMETER_FUNCTION((int), lazy_defaults, tag,
(required
(name, *)
)
(optional
(value, *, name.foo)
(index, *, name.bar)
)
)
{
return 0;
}
} // namespace test
int main()
{
using namespace test;
f(
values(S("foo"), 1.f, 2)
, S("foo")
);
f(
tester = values(S("foo"), 1.f, 2)
, name = S("foo")
);
int index_lvalue = 2;
f(
tester = values(S("foo"), 1.f, 2)
, name = S("foo")
, value = 1.f
, test::index = index_lvalue
);
f(
values(S("foo"), 1.f, 2)
, S("foo")
, 1.f
, index_lvalue
);
g(
values(S("foo"), 1.f, 2)
, S("foo")
, 1.f
#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
, as_lvalue(2)
#else
, 2
#endif
);
h(
values(S("foo"), 1.f, 2)
, S("foo")
, 1.f
#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
, as_lvalue(2)
#else
, 2
#endif
);
h2(
tester = values(S("foo"), 1.f, 2)
, name = S("foo")
, value = 1.f
);
class_ x(
values(S("foo"), 1.f, 2)
, S("foo"), test::index = 2
);
x.f(
values(S("foo"), 1.f, 2)
, S("foo")
);
x.f(
tester = values(S("foo"), 1.f, 2)
, name = S("foo")
);
x.f2(
values(S("foo"), 1.f, 2)
, S("foo")
);
x.f2(
tester = values(S("foo"), 1.f, 2)
, name = S("foo")
);
class_ const& x_const = x;
x_const.f(
values(S("foo"), 1.f, 2)
, S("foo")
);
x_const.f(
tester = values(S("foo"), 1.f, 2)
, name = S("foo")
);
x_const.f2(
values(S("foo"), 1.f, 2)
, S("foo")
);
x_const.f2(
tester = values(S("foo"), 1.f, 2)
, name = S("foo")
);
x_const.f2(
tester = values(S("foo"), 1.f, 2)
, name = S("foo")
);
class_::f_static(
values(S("foo"), 1.f, 2)
, S("foo")
);
class_::f_static(
tester = values(S("foo"), 1.f, 2)
, name = S("foo")
);
#if ! defined(BOOST_NO_SFINAE) && ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
assert(sfinae("foo") == 1);
assert(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.
assert(sfinae1("foo") == 1);
# endif
assert(sfinae1(1) == 0);
#endif
lazy_defaults(
name = udt(0,1)
);
lazy_defaults(
name = 0
, value = 1
, test::index = 2
);
return 0;
}