c++11 iteration and warnings

Started by
25 comments, last by Ravyne 11 years, 1 month ago

I want to iterate through an object in c++11, and like the new syntax. If I have the following code:


for (auto x : object) {
    ...
}

I have a case where I don't want to use 'x'. That will produce a warning, as expected. How do I best suppress this warning?

I suppose I can add a line (void)x; but maybe there is some better way?

If there is no better way, can I be sure that the void reference to 'x' generates no code?

There is of course the old way of using iterators, but it looks much better with the new way of doing it. Or tell the compiler to ignore these warnings, which I do not want to do.

[size=2]Current project: Ephenation.
[size=2]Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/
Advertisement

There is of course the old way of using iterators, but it looks much better with the new way of doing it. Or tell the compiler to ignore these warnings, which I do not want to do.

I don't know why you're iterating without using the reference at all, but I'd do the following:


for (auto i = object.cbegin(); i != object.cend(); ++i) {
    ...
}

It shouldn't be any worse in performance than a range based for-each loop (I imagine it'd be exactly the same, with optimizations turned on).

As C++11 currently is, there's no way to do a range-based for loop without a range declaration.

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

I have a case where I don't want to use 'x'.

Can you elaborate on the use-case?

Apart from implementing your garden variety REPEAT 10; this seems a little suspect.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Apart from implementing your garden variety REPEAT 10; this seems a little suspect.

The iteration has side effects that I need. See example at https://github.com/larspensjo/entityx#systems-implementing-behavior

[size=2]Current project: Ephenation.
[size=2]Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/

Err, I realize I missread the initial question... (void)x; will do the trick and it generates no code, what could it possibly generate? The downside is still in the case that not using x means you "are" going to have a copy taking place into "auto x" though as part of the loop.

using the new modified syntax, I'd go with the following:

for( auto ibegin = object.cbegin(), iend = object.cend(); ibegin!=iend; ++ibegin )
...

this avoids the useless copy construction of the 'x' value.

I want to iterate through an object in c++11, and like the new syntax. If I have the following code:


for (auto x : object) {
    ...
}

I have a case where I don't want to use 'x'. That will produce a warning, as expected. How do I best suppress this warning?

I suppose I can add a line (void)x; but maybe there is some better way?

If there is no better way, can I be sure that the void reference to 'x' generates no code?

There is of course the old way of using iterators, but it looks much better with the new way of doing it. Or tell the compiler to ignore these warnings, which I do not want to do.

Hiding side effects behind iteration seems... gross to me.

It's more verbose, but I'd rather see your code look like this, just for sake of clarity:
struct MovementSystem : public System<MovementSystem> {
  void update(EntityManager &es, EventManager &events, double dt) override {
    for (auto& entity : es.entities_with_components<Position, Direction>()) {
      std::shared_ptr<Position> position(entity.get_component<Position>());
      std::shared_ptr<Direction> direction(entity.get_component<Direction>());

      position->x += direction->x * dt;
      position->y += direction->y * dt;
    }
  }
};
It took me several read-throughs of your code to figure out that it's equivalent to this. IMHO that's bad, because it means your system is not intuitive enough, or idiomatic in terms of how iteration typically works in C++.

It's also clearer that this code will optimize cleanly. Moreover, if you know you don't want to affect an object's lifetime during the update, you can opt for raw pointers instead of shared_ptr which gives you a little less overhead, assuming that that sort of micro-optimization is relevant.

That's just my opinion, though :-)

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

If you're not using x, its probably more efficient to iterate over an integer count with size of the number of objects.

throw table_exception("(? ???)? ? ???");

If there is no better way, can I be sure that the void reference to 'x' generates no code?

There is of course the old way of using iterators, but it looks much better with the new way of doing it. Or tell the compiler to ignore these warnings, which I do not want to do.

If you use "auto& x" or "const auto& x" as the loop variable, there are no copies.
And if I understand correctly, the standard guarantees (void)x; does nothing with x either:
http://stackoverflow.com/questions/689677/casting-unused-return-values-to-void

If there is no better way, can I be sure that the void reference to 'x' generates no code?

There is of course the old way of using iterators, but it looks much better with the new way of doing it. Or tell the compiler to ignore these warnings, which I do not want to do.

If you use "auto& x" or "const auto& x" as the loop variable, there are no copies.
And if I understand correctly, the standard guarantees (void)x; does nothing with x either:
http://stackoverflow.com/questions/689677/casting-unused-return-values-to-void

While all true, "auto& x" still may cause something to be done in the iteration which may not be needed/desired. I.e. de-referencing the iterator in order to get the reference initialized. At this point you have to look at assembly to figure out if the compiler is doing what you intend (simply dropping the item and optimizing it away) or if it is actually doing unused work behind your back. As this is a relatively new language feature, who knows if the compilers are really optimizing this specific case correctly, I don't trust compilers that much and prefer to be explicit.

While all true, "auto& x" still may cause something to be done in the iteration which may not be needed/desired. I.e. de-referencing the iterator in order to get the reference initialized. At this point you have to look at assembly to figure out if the compiler is doing what you intend (simply dropping the item and optimizing it away) or if it is actually doing unused work behind your back. As this is a relatively new language feature, who knows if the compilers are really optimizing this specific case correctly, I don't trust compilers that much and prefer to be explicit.

I'd prefer to always write the code as nicely as the language allows and if it matters, verify the compiler is doing the right thing. That may be more of an idealist approach while yours is a more practical one. Considering that range-for and auto are probably the most-used features of the new standard, I think support will be pretty good. Lars' library isn't exactly shy of using C++11 to begin with.

This topic is closed to new replies.

Advertisement