
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