|
Boost : |
From: Vaclav Vesely (vaclav.vesely_at_[hidden])
Date: 2006-03-26 14:19:58
David Abrahams wrote:
> Yes, the library ought to contain something like that, as I have been
> saying for years. Probably it should be spelled something like:
>
> new_<shared_ptr<T> >(a, b, c, ...)
>
> new_<auto_ptr<T> >(a, b, c, ...)
>
> Unfortunately, really making these functions work correctly for more
> than about 5 or 6 arguments is currently not feasible because of
> what's known as "the forwarding problem" (google it).
> Boost Consulting is working on a project where we'll need this
> functionality, so I hacked up the enclosed. I'm going to generalize
> it (and hopefully, optimize compilation speed) a bit and try to get it
> into Boost. In the meantime, enjoy.
IMHO const reference forwarding and explicit wrapping of non-const
reference parameters with boost::ref is comfortable enough and feasible
with current compilers. See the attachment.
If there will be there a will to add my implementation into Boost, I
will write an appendix to the Best Practices.
Regards,
Vaclav
#define BOOST_TEST_MAIN
#include <boost/intrusive_ptr.hpp>
#include <boost/mpl/list.hpp>
#include <boost/new.hpp>
#include <boost/noncopyable.hpp>
#include <boost/ref.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/test/unit_test.hpp>
#include <string>
//-----------------------------------------------------------------------------
static int g3 = 0;
static int g5 = 0;
class X:
boost::noncopyable
{
public:
X(
int a1 = 0,
int* a2 = NULL,
int& a3 = g3,
std::string const& a4 = "",
const int& a5 = g5,
int a6 = 0,
int a7 = 0,
int a8 = 0,
int a9 = 0,
int a10 = 0)
:
m_ref_count(0),
m1(a1),
m2(a2),
m3(a3),
m4(a4),
m5(a5),
m6(a6),
m7(a7),
m8(a8),
m9(a9),
m10(a10)
{
}
int m_ref_count;
int m1;
int* m2;
int& m3;
std::string m4;
const int& m5;
int m6;
int m7;
int m8;
int m9;
int m10;
};
void intrusive_ptr_add_ref(X* x)
{
++(x->m_ref_count);
}
void intrusive_ptr_release(X* x)
{
if(--(x->m_ref_count) == 0)
delete x;
}
//-----------------------------------------------------------------------------
typedef boost::mpl::list<
boost::intrusive_ptr<X>,
boost::shared_ptr<X>
> test_types;
BOOST_AUTO_TEST_CASE_TEMPLATE(new_test, PtrType, test_types)
{
int a1 = 1;
int* a2 = new int(2);
int& a3 = a1;
std::string a4("4");
int a5 = 5;
int a6 = 6;
int a7 = 7;
int a8 = 8;
int a9 = 9;
int a10 = 10;
PtrType sp;
sp = boost::new_<PtrType>();
BOOST_CHECK(sp);
sp = boost::new_<PtrType>(a1);
BOOST_CHECK(sp);
BOOST_CHECK_EQUAL(sp->m1, a1);
sp = boost::new_<PtrType>(a1, a2);
BOOST_CHECK(sp);
BOOST_CHECK_EQUAL(sp->m1, a1);
BOOST_CHECK_EQUAL(sp->m2, a2);
sp = boost::new_<PtrType>(a1, a2, boost::ref(a3));
BOOST_CHECK(sp);
BOOST_CHECK_EQUAL(sp->m1, a1);
BOOST_CHECK_EQUAL(sp->m2, a2);
BOOST_CHECK_EQUAL(&sp->m3, &a3);
sp = boost::new_<PtrType>(a1, a2, boost::ref(a3), a4);
BOOST_CHECK(sp);
BOOST_CHECK_EQUAL(sp->m1, a1);
BOOST_CHECK_EQUAL(sp->m2, a2);
BOOST_CHECK_EQUAL(&sp->m3, &a3);
BOOST_CHECK_EQUAL(sp->m4, a4);
sp = boost::new_<PtrType>(a1, a2, boost::ref(a3), a4, a5);
BOOST_CHECK(sp);
BOOST_CHECK_EQUAL(sp->m1, a1);
BOOST_CHECK_EQUAL(sp->m2, a2);
BOOST_CHECK_EQUAL(&sp->m3, &a3);
BOOST_CHECK_EQUAL(sp->m4, a4);
BOOST_CHECK_EQUAL(&sp->m5, &a5);
sp = boost::new_<PtrType>(a1, a2, boost::ref(a3), a4, a5, a6);
BOOST_CHECK(sp);
BOOST_CHECK_EQUAL(sp->m1, a1);
BOOST_CHECK_EQUAL(sp->m2, a2);
BOOST_CHECK_EQUAL(&sp->m3, &a3);
BOOST_CHECK_EQUAL(sp->m4, a4);
BOOST_CHECK_EQUAL(&sp->m5, &a5);
BOOST_CHECK_EQUAL(sp->m6, a6);
sp = boost::new_<PtrType>(a1, a2, boost::ref(a3), a4, a5, a6, a7);
BOOST_CHECK(sp);
BOOST_CHECK_EQUAL(sp->m1, a1);
BOOST_CHECK_EQUAL(sp->m2, a2);
BOOST_CHECK_EQUAL(&sp->m3, &a3);
BOOST_CHECK_EQUAL(sp->m4, a4);
BOOST_CHECK_EQUAL(&sp->m5, &a5);
BOOST_CHECK_EQUAL(sp->m6, a6);
BOOST_CHECK_EQUAL(sp->m7, a7);
sp = boost::new_<PtrType>(a1, a2, boost::ref(a3), a4, a5, a6,
a7, a8);
BOOST_CHECK(sp);
BOOST_CHECK_EQUAL(sp->m1, a1);
BOOST_CHECK_EQUAL(sp->m2, a2);
BOOST_CHECK_EQUAL(&sp->m3, &a3);
BOOST_CHECK_EQUAL(sp->m4, a4);
BOOST_CHECK_EQUAL(&sp->m5, &a5);
BOOST_CHECK_EQUAL(sp->m6, a6);
BOOST_CHECK_EQUAL(sp->m7, a7);
BOOST_CHECK_EQUAL(sp->m8, a8);
sp = boost::new_<PtrType>(a1, a2, boost::ref(a3), a4, a5, a6, a7, a8, a9);
BOOST_CHECK(sp);
BOOST_CHECK_EQUAL(sp->m1, a1);
BOOST_CHECK_EQUAL(sp->m2, a2);
BOOST_CHECK_EQUAL(&sp->m3, &a3);
BOOST_CHECK_EQUAL(sp->m4, a4);
BOOST_CHECK_EQUAL(&sp->m5, &a5);
BOOST_CHECK_EQUAL(sp->m6, a6);
BOOST_CHECK_EQUAL(sp->m7, a7);
BOOST_CHECK_EQUAL(sp->m8, a8);
BOOST_CHECK_EQUAL(sp->m9, a9);
sp = boost::new_<PtrType>(a1, a2, boost::ref(a3), a4, a5, a6, a7, a8, a9,
a10);
BOOST_CHECK(sp);
BOOST_CHECK_EQUAL(sp->m1, a1);
BOOST_CHECK_EQUAL(sp->m2, a2);
BOOST_CHECK_EQUAL(&sp->m3, &a3);
BOOST_CHECK_EQUAL(sp->m4, a4);
BOOST_CHECK_EQUAL(&sp->m5, &a5);
BOOST_CHECK_EQUAL(sp->m6, a6);
BOOST_CHECK_EQUAL(sp->m7, a7);
BOOST_CHECK_EQUAL(sp->m8, a8);
BOOST_CHECK_EQUAL(sp->m9, a9);
BOOST_CHECK_EQUAL(sp->m10, a10);
delete a2;
}
//-----------------------------------------------------------------------------
#ifndef BOOST_NEW_HPP_INCLUDED
#define BOOST_NEW_HPP_INCLUDED
#include <boost/config.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
namespace boost
{
#if !defined(BOOST_MAX_NEW_ARITY)
#define BOOST_MAX_NEW_ARITY 10
#endif
#define BOOST_NEW_TEMPLATE(z, n, d) \
template<typename T BOOST_PP_ENUM_TRAILING_PARAMS(n, typename A)> \
T new_(BOOST_PP_ENUM_BINARY_PARAMS(n, A, const& a)) \
{ \
return T(new T::element_type(BOOST_PP_ENUM_PARAMS(n, a))); \
} \
/**/
BOOST_PP_REPEAT(BOOST_PP_INC(BOOST_MAX_NEW_ARITY), BOOST_NEW_TEMPLATE,
BOOST_PP_EMPTY())
#undef BOOST_NEW_TEMPLATE
} // namespace boost
#endif // #ifndef BOOST_NEW_HPP_INCLUDED
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk