Re: The joy (?) of C++98 argument forwarding
On 04.05.2010 15:01, * Alf P. Steinbach:
On 04.05.2010 14:56, * DeMarcus:
Alf P. Steinbach wrote:
Consider ...
[snip]
Shared< Foo > r4( newObject(), args( 42, "blah blah" ) );
[snip]
Is the notation in the 'test' routine OK, or would it be better (in
some sense) with some macro, e.g. like
Shared< Foo > r( CPPX_NEW_SHARED( 42, "blah blah" ) );
?
At least consider CPPX_NEW_SHARED_FOO( 42, "blah blah" ). Otherwise the
macro name would be as non-intuitive as
CPPX_NEW_SHARED( PI, 21.45, time() )
Well for the example above the type is implicit in the declaration, so
it would be redundant to repeat it there.
On the other hand you have a point -- I didn't think of it -- for an
actual argument in a routine call.
On the third hand, we usually don't specify arguments there for value
arguments.
Keyboard gremlin was active, I meant, "we usually don't specify the type for an
actual argument for a value argument".
Can't you do the wrapper with a template instead of a macro?
Not sure what you mean; the Shared shared pointer type is templated, as
the example usage code shows.
Oh, I think I see what you meant now. You probably thought that the newObject()
call produces a Foo*.
It doesn't, it's just a placeholder thing, of fixed type.
In
Shared< Foo > r4( newObject(), args( 42, "blah blah" ) );
the arguments are just arguments, and it's the Shared pointer constructor that
does the new'ing.
Happily the Shared definition is not more code than I can show in Usenet article[1].
The constructor invoked by the above is the second one:
<code>
namespace progrock{ namespace cppx{
enum NewObject {};
inline NewObject newObject() { return NewObject(); }
template< typename Type >
class Shared
: protected detail::SharedBase< Type >
{
private:
typedef detail::SharedBase< Type > Base;
public:
typedef Type Object;
Shared( NewObject )
: Base( detail::newRefCounted< Object >( EmptyArgPack() ) )
{}
template< class ArgPack >
Shared( NewObject, ArgPack const& args )
: Base( detail::newRefCounted< Object >( args ) )
{}
template< class OtherType >
Shared( std::auto_ptr< OtherType > p )
: Base(
detail::newRefCounted< detail::RawPtrHolder< OtherType > >(
args( p.get() ) ),
p.get()
)
{
p.release();
}
template< class OtherType >
Shared( Shared< OtherType > const& other )
: Base( other )
{}
void swapWith( Shared& other )
{
Base::swapWith( other );
}
Shared& operator=( Shared other )
{
swapWith( other ); return *this;
}
Object* rawPtr() const { return myObject; }
Object& rawRef() const { return *rawPtr() }
Object& operator*() const { return rawPtr(); }
Object* operator->() const { return rawPtr(); }
};
} } // namespace progrock::cppx
template< class Type >
inline CPPX_IMPLEMENT_SWAP( progrock::cppx::Shared< Type > )
</code>
The question still stands, is it OK with notation like
Shared< Foo > r4( newObject(), args( 42, "blah blah" ) );
or would it be better in some sense with some macro, e.g. like
Shared< Foo > r( CPPX_NEW_SHARED( 42, "blah blah" ) );
?
Cheers,
- Alf
Notes:
[1] There is a subtlety here regarding copy construction. The templated
constructor that looks like a copy constructor isn't one. The compiler generated
copy constructor invokes the one of the base class.