|
Boost : |
From: ION_G_M (ION_G_M_at_[hidden])
Date: 2005-02-18 07:29:04
Hello to all,
while developing Boost Shmem, I wanted to create a constructor proxy
to emulate c++ dynamic object allocation syntax when creating shared
memory objects using a proxy object in the following way:
T * ptr = shmem_segment.create<T>("ObjectName")[size]
/*proxy returned here, calls operator() of the object*/
(arg1, arg2, ...argN);
Shared memory is allocated and the object is constructed. I want the
arguments to be deduced automatically in the proxy object function call
to preserve this syntax. I also want to avoid _all_ parameter copying.
I mean, if I can deduce that an argument can be passed by value or by
referenced using this syntax, great. But, between copying _all_
arguments and passing a reference in _all_, I prefer the second.
Trying to find a correct proxy for this, I had many problems when
passing temporary arguments and hardcoded constants to the proxy. Right
now I am using some ugly casts to avoid the copies, but this has some
side-effects. I will explain the problem in the following code:
#include <new>
//Object to be constructed
struct Ctor2Arg
{
Ctor2Arg(const int &const_ref, int &non_const_ref){}
};
//"Clean" proxy
template <class T>
struct constructor_proxy_t
{
template<class T0, class T1>
void operator()(T0 & t0, T1 & t1) const
{
char m_mem[sizeof(T)];
//Call constructor and destructor
T *ptr = new(m_mem)T(t0, t1);
ptr->~T();
}
};
//Ugly cast proxy
template <class T>
struct ugly_constructor_proxy_t
{
template<class T0, class T1>
void operator()(const T0 & t0, const T1 & t1) const
{
char m_mem[sizeof(T)];
//Convert all refs to non-const refs
T0 & t0ref = const_cast<T0 &>(t0);
T1 & t1ref = const_cast<T1 &>(t1);
//Call constructor and destructor, non-const
//refs can be converted to const refs
T *ptr = new(m_mem)T(t0ref, t1ref);
ptr->~T();
}
};
//Main function
int main()
{
//Construct normal and ugly proxies
constructor_proxy_t<Ctor2Arg> proxy;
ugly_constructor_proxy_t<Ctor2Arg> ugly_proxy;
//One const int and one non-const int
const int dummy_const = 0;
int dummy_non_const = 0;
//This is ok, calls:
//constructor_proxy_t<Ctor2Arg>::operator()
//<int const ,int>(const int & t0=0, int & t1=0)
proxy(dummy_const, dummy_non_const);
//Both of these calls do not compile in VC7.1 or gcc 3.4.3,
//tries to call constructor_proxy_t<Ctor2Arg>::operator()
//<int, int>(int & t0=5, int & t1=0)
//
// gcc 3.4.3 error
//
//error: no match for call to
// `(constructor_proxy_t<Ctor2Arg>) (int, int&)'
//candidates are:
// void constructor_proxy_t<T>::operator()(T0&, T1&)
// [with T0 = int, T1= int, T = Ctor2Arg]
//
//Obviously, compilers are right, but
//it wouldn't be more logical to call
//<int const, int> specialization since a
//temporary is a constant object?
// proxy(dummy_non_const+5, dummy_non_const);
// proxy(dummy_const+5, dummy_non_const);
//This is ok, calls:
//ugly_constructor_proxy_t<Ctor2Arg>::operator()
//<int,int>(const int & t0=0, const int & t1=0)
ugly_proxy(dummy_const, dummy_non_const);
//These are ok, call:
//ugly_constructor_proxy_t<Ctor2Arg>::operator()
//<int,int>(const int & t0=5, const int & t1=0)
ugly_proxy(dummy_non_const+5, dummy_non_const);
ugly_proxy(dummy_const+5, dummy_non_const);
//This compiles but it should not, since
//I am passing a const object as second parameter
//so Ctor2Arg obj(dummy_const, dummy_const)
//does not compile. This calls:
//ugly_constructor_proxy_t<Ctor2Arg>::operator()
//<int,int>(const int & t0=0, const int & t1=0)
ugly_proxy(dummy_const, dummy_const);
return 0;
}
My question is, has anyone a better way to write the proxy object
without ugly casts, no side-effects (I mean, the proxy call should
compile only if the constructor compiles), preserving a clean calling
syntax, and _no_ object copies at all?
And the second question is: when a temporary is passed to a template,
why non-const argument is deduced in the function call?
Thank you, regards,
/Ion
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk