Boost logo

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