Re: Is UniversalPointer a good idea?
I want to be able to receive a polymorphic object to a class. However, I
want this class to be able to receive all kinds of pointers there are in
C++. Since this class is going to be an interface, I don't really want
to have one method for each pointer type since that would be too tedious
for the users of the interface.
I came up with the following idea of a UniversalPointer to take care of
all kinds of circumstances.
[...snip...]
#include <iostream>
#include <memory>
template<class T>
class UniversalPointer
{
public:
UniversalPointer( T* pointer )
: universalPointer_( pointer ) {}
UniversalPointer( T& reference )
: universalPointer_( &reference ) {}
UniversalPointer( T&& reference )
: universalPointer_( &reference ) {}
UniversalPointer( const std::unique_ptr<T>& uPointer )
: universalPointer_( uPointer.get() ) {}
UniversalPointer( const std::shared_ptr<T>& sPointer )
: universalPointer_( sPointer.get() ) {}
[...snip...]
private:
T* universalPointer_;
};
I can't imagine a situation in which I would use something like this.
[...snip...]
int fnc( UniversalPointer<Number> upn )
{
upn->increase();
return upn->getNumber();
}
int main()
{
Number number( 0 );
std::unique_ptr<Number> uptrNumber( new Number( 42 ) );
std::cout << fnc( &number ) << std::endl;
std::cout << fnc( number ) << std::endl;
std::cout << fnc( std::move( number ) ) << std::endl;
std::cout << fnc( Number( 4710 ) ) << std::endl;
std::cout << fnc( uptrNumber ) << std::endl;
std::cout <<
fnc( std::shared_ptr<Number>( std::move( uptrNumber ) ) )
<< std::endl;
Wny not simply write this?
int fnc( Number & u )
{
n.increase();
return n.getNumber();
}
Surely you can dereference a pointer at the call site manually to
invoke it.
I agree, that's much more clean.
And what is the purpose of doing the following?
std::cout << fnc( std::move( number ) ) << std::endl;
std::cout << fnc( Number( 4710 ) ) << std::endl;
Do you really want `fnc` to take and mutate *both* lvalues as well as
rvalues? Usually, you want just one kind of non-const reference where
allowing the other kind would actually be an error (in most cases).
You're completely right. Thanks for the insight!
My case was this. Instead of a Number, I wanted to provide a Visitor.
This visitor could be an object that was first created and then
initialized before provided to the function in question. I also wanted
to provide the same visitor to other objects so it couldn't be destroyed
in a near future. That visitor would then be an lvalue that could be
modified, i.e. someFnc( IVisitor& n );
Now, I also wanted to provide a visitor that didn't need any
initialization and that I only wanted to provide one time. A typical
such visitor could be a PrintVisitor or EmptyVisitor, i.e. we may want
to write someFnc( PrintVisitor() ); since it just felt awkward to first
declare it like the following.
PrintVisitor pv;
someFnc( pv );
I couldn't use function parameter const IVisitor& since then I would be
forced to create the Visitor interface with both const and non-const
methods, e.g.
class IVisitor
{
public:
virtual ~IVisitor() {}
virtual int doSomething() const = 0;
virtual int doSomething() = 0;
};
And the above wasn't an option.
Even though rvalues like in someFnc( PrintVisitor() ); aren't really
const, they should probably as you say, be seen as such since altering
an object that nobody will use is very awkward.
I think I got stuck in this design smell during too much focus on
creating a simple interface.
Thanks,
Daniel
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]