C ++ generic list assignment
I've clearly been stuck in the Java lands for too long ... Is it possible to use the C ++ equivalent for the following Java code:
interface Foo {}
class Bar implements Foo {}
static List<Foo> getFoo() {
return new LinkedList<Foo>();
}
static List<Bar> getBar() {
return new LinkedList<Bar>();
}
List<? extends Foo> stuff = getBar();
Where Foo is a subclass of the Bar class.
So in C ++ ....
std::list<Bar> * getBars()
{
std::list<Bar> * bars = new std::list<Bar>;
return bars;
}
std::list<Foo> * stuff = getBars();
Hope this makes sense ....
a source to share
No, in my opinion it doesn't make sense in C ++.
First, you return a link that no longer exists. To avoid this, you can pass your std :: list as a reference parameter that needs to be changed in the function like
void fillFoos( std::list< Foo > & foos )
Secondly, foos are not bars and cannot be copied to each other, but I think that if you provide the correct copy operator.
But if you are using inheritance all your foos and bars must be pointers (and if you can use smart-as as shared_ptr pointers from boost or tr1). But that doesn't mean the copy works.
I'm not sure what you want to do, but porting from JAVA to C ++ doesn't work in this case. If you create foos, they will automatically get all of the bars.
std::list< Foo > foos; // just work fine
If you want a list of bars built like foos:
std::list< Bar * > bars;
bars.push_back( new Foo() );
Or how I would put it in real C ++ code with shared_ptr:
typedef boost::shared_ptr< Bar >;
typedef boost::shared_ptr< Foo >;
typedef std::list< BarPtr > BarList;
BarList bars;
bars.push_back( FooPtr( new Foo() ) );
a source to share
Edit
std::list<Bar> & getBars()
to
std::list<Bar> getBars()
This will in principle return by value, but the copy mechanism will be copied, so compiler optimizations should be able to optimize
std::list<Bar> bars (getBars());
to not include a copy constructor and just build bars
.
Also, there is a move constructor in C ++ 0x, so the above code is efficient even if copy / move is not eliminated for some reason.
EDIT for the overlooked subclass question:
In general, it cannot be done purely in C ++ (I assume it Foo
is a superclass Bar
, otherwise what you are doing makes little sense). Perhaps this is possible with some black magic reinterpret_cast
, but I would strongly advise it.
The closest approximation is probably this (with getBars()
adjusted accordingly):
std::list <Bar*> bars (getBars ());
std::list <Foo*> foos (bars.begin (), bars.end ());
However, this puts some non-trivial memory management burden on you. Using some kind of autoruners might help, but as far as I remember, containers can only be used shared_ptr
.
Finally, the Foo
/ class hierarchy Bar
must use virtual functions, otherwise what you want to do will almost certainly not work (i.e. unless you really want to ignore any overrides in the subclass).
a source to share
you need an object to support constructors for these operations, so you shouldn't return a reference, not a direct object to be copied, otherwise return a pointer, that is:
std::list<Bar> getBars()
{
std::list<Bar> Bars;
return Bars;
}
or
std::list<Bar>* getBars()
{
return new std::list<Bar>();
}
std :: list supports copying objects from another list, but only if this list is of the same type, i.e. you cannot copy from std::list<Bar>
to std::list<Foo>
implicitly, but you can copy from std::list<Foo>
to std::list<Foo>
.
a source to share
Either I am getting something completely wrong here, or your Java code is not working. I just tried it. This does not work. The reason is that generic containers in Java are not covariant (which means that this also doesn't work if it Bar
is a subclass Foo
). Second, if Foo
is a subclass Bar
, you can assign Foo
references to Bar
, but not vice versa (neither in Java nor C ++).
Containers in C ++ are also non-covariant. But you can do
std::list<Foo*> FooList;
// fill FooList;
std::list<Bar*> BarList(FooList.begin(), FooList.end());
if it Foo
is a subclass Bar
. However, this will cause all pointers in to FooList
be copied to BarList
. This means that if you change FooList
after adding or removing items, those changes will not be reflected in BarList
.
a source to share