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 ....

+2


a source to share


6 answers


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() ) );

      

+3


a source


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).

+4


a source


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>

.

+2


a source


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

.

+2


a source


everything is fine except that you are returning a reference to a local variable. it is held on the stack and will be deallocated after the function returns.

+1


a source


Also, the new std :: list will return a pointer, not a link.

0


a source







All Articles