Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 08 Aug 2000
Offline Last Active Aug 17 2016 04:05 AM

#5301356 Overall Strategy For Move-Semantics? [C++11]

Posted by on 19 July 2016 - 07:05 AM

Anyway, I seem to not take well to the heat and I have become too emotionally invested in the issues here for some reason. I will remove the offending piece. I still believe there is a point to be made but I have neither the time nor energy anymore and it simply detracts from the core issues of the thread.

To reiterate the core points relevant to this thread: from a C++11 viewpoint, (4) is the best practice in my opinion. If you are worried about team members being up-to-date on move-semantics, (3) is a reasonable alternative at the cost of a little bit of boilerplate when you need to invoke it with a true copy but should flag most unintended copies as a compile error. I do not like (2) at all since it combines the potential of the unintended misuse of (4) with code duplication and an untidy interface.
Edit: However, if (4) is not advisable I would probably rather favor distinctly named functions which clearly describe the semantics (like for example moveXInto and copyXInto) and are backed up by the compiler (rvalue reference and const reference, respectively).

#5301348 Overall Strategy For Move-Semantics? [C++11]

Posted by on 19 July 2016 - 05:59 AM

I had to fix that for you. A competent programmer does not ignore half the language or refuse to even read up on things. Even when the current work environment does not allow it, a competent programmer spends a bit time reading up on things and trying them out. Ideally officially as part of their job in formal or informal training or if push comes to shove in their hobby projects.

I don't know if you realise if you're being quite insulting or not...

It was probably a bit sharp but Kylotan just keeps rubbing me entirely the wrong way and it's getting hot here.

I should probably have said that a competent programmer can easily pick up on C++11 which relatively little work. Sure, if your work does not use any C++11 real life might no allow you to get proficiency there. But part of being 'competent' is also being able to read up quickly once things become relevant. And honestly, just reading the C++11-page of Wikipedia already takes you a very long way.

And most importantly, a competent programmer strives for best practices. I explained in #17 above why I think the solution proposed by Kylotan is actually the worst of both worlds.

Edit: Additionally, the only real use case I have seen for the issue we are arguing about here was in heavy-duty preprocessing tools. Telling the new guy on that part of the project "by the way, considering the nature of our data we make heavy use of move-semantics. If you haven't read up on that, here is a link" does not seem to be much of a stretch. Especially since the code probably already contains lots of std::move then which should ring additional warning bells even for the uninitiated.

#5301345 Overall Strategy For Move-Semantics? [C++11]

Posted by on 19 July 2016 - 05:47 AM

I'm well aware of compromises you have to accept in a working environment. I could live with saying "we do not use C++11 features in our codebase".

When C++11 or above is allowed however (completely or selected features), one should strive for the best practices. I see absolutely no point in obsessive overloads and code duplication for the rest of eternity just to compensate for some hypothetical least competent allowed programmer. Especially since (2) from above is more or less the worst scenario. An unobservant user can still easily do an expensive copy, just as in (4). I'd much have (3) in that case. At least then only a move is allowed and a copy requires explicit, clearly visible extra work (both for the writer and the reader).

It removes the possibility of an accidental copy and avoids excessive overloading (which just makes an interface very hard to read). If we have to guard against horrible team members (3) should be the way to go. Another way would be to go with a simple old-school reference and documenting the content on return is somehow "unspecified but valid", but considering we only did that for bad users, I'd much rather have (3) because an std::move rings warning bells much more efficiently compared to a note in the (probably unread) documentation.

#5301313 [C++] Changing Fore And Back Color Of Text

Posted by on 19 July 2016 - 12:30 AM

@OP: Dwarf Fortress is not using the system terminal/console for graphics. It has its own rendering system. Two actually, one using SDL and one using OpenGL.

Well, last time I did that research (which was admittedly a few years ago) they were simply using the SDL-variant of pdcurses. Personally I would advise someone new to use that as starting point instead of trying to roll something by hand. The startup time is going to be significantly quicker and if you are interested in text mode games you probably don't want to spend too much time messing about with OpenGL...

#5301265 [C++] Changing Fore And Back Color Of Text

Posted by on 18 July 2016 - 03:33 PM

If you aim in the direction of Dwarf Fortress you might be better served by something like pdcurses. There is also libtcod but there are some design decisions in there that never sat well with me and it's not in active development. Different libraries may have sprung up since the last time I investigated the DF-related ecosystem though.

#5301244 Compilers

Posted by on 18 July 2016 - 12:59 PM

I would strongly advise against using a MinGW-derivate as a beginner and I am saying that as someone who uses MinGW for all his hobby work and enjoys that.

C++ has enough problems and pitfalls for a beginner. You should not add even more problems on top of that by using the non-standard compiler for your OS.

And if you still disregard my advise above, at least get a proper IDE. Personally I have come to like QtCreator a lot (and I do not use an iota of Qt).

#5300841 Is This Evil(Reserve Memory In Template Linked List)

Posted by on 15 July 2016 - 12:38 AM

Apart from the fact that you seem to be throwing away type information needlessly what worries me first and foremost is trying to memcpy stuff around. The only types you are allowed to do that with are types for which std::is_trivially_copyable evaluates to true.

Additionally, I'm not really sure what you are trying. I have the strong suspicion though you might be better served with either std::deque or by using a standard std::list with a custom pool-based allocator.

#5300748 Newbie Question About Std:vector

Posted by on 14 July 2016 - 10:47 AM

A valid move constructor/assignment operator needs to leave the object moved out of in a "valid but unspecified state". Actually the language does not require that but anything which you want to put into a standard library container needs to do that and I have also never seen a scenario where that was not possible.

One common pattern to do that is to implement the move constructor by delegating to the default constructor and then swapping the members.

I'd say the core problem is the OP described the problem in a too general way. I strongly suspect m_aPtr and m_bPtr are resources owned by Problem. In this case the solution is extremely simple: use std::unique_ptr instead of raw pointers and everything fixed itself. Problem is no longer copyable (because unique_ptr are not) but Problem is movable (because unique_ptr are and the compiler will create a default move-constructor based on the unique_ptr move semantics).
That's usually the best case: you have a complicated class but you do not even need to bother making it copyable and/or movable because the member data already enforces what it needs/allows.

Edit: If you find yourself explicitly writing a lot copy/move constructor or assignment operators that's usually a sign of either of two things:
1) you are doing something wrong.
2) you are writing a lot of very low-level primitives (similar in scope to for example unique_ptr or shared_ptr) in preparation to use them in your more complex classes.

#5300739 Newbie Question About Std:vector

Posted by on 14 July 2016 - 09:43 AM

If you have a reasonably modern compiler (that is, not half a decade old or more) then you do not need full copy semantics (these can be fairly difficult to get right because they mess with strong ownership semantics).

In any case, unless you know definitely that a class should be able to be copyable, you should forbid it:
class MyClass
   MyClass(const MyClass&) = delete;
   MyClass& operator = (const MyClass&) = delete;
see also boost::noncopyable.

If you forbid copying a class, then you need to make it movable to use it in a vector, see move constructors and move assignment.

Another alternative is to manage m_aPTr and m_bPTr using std::shared_ptr. I strongly advise against getting used to that too much. A key skill in software development is deciding (and enforcing) who is responsible for what and a shared_ptr hides this problem. That can lead to some pretty messy and annoying systems but when starting out it might be a useful bandaid to avoid a lot of problems to hit you all at the same time. As long as you realize it's still a bandaid and not a solution for everything it's probably not too bad.

Also, when you need to initially fill a vector it is a good idea to call reserve first with a reasonable value to avoid excessive reallocations.

#5300667 Skeletal animation optimization

Posted by on 14 July 2016 - 02:07 AM

I just figured something out. If I run my code in 'Release' configuration I get 0.2 ms frame time without animation and 0.3 ms frame time with. That's much more acceptable. Why does 'Debug' configuration result in such drastic change? Does this have something to do with DirectXMath library?

Debug builds are always slow. They contain checks which you would not do in a final build but are useful during development, they contain a lot of extra information useful for debugging, they are intentionally not optimized or optimized in a more limited way. MSVC also adds, for example, alternative memory management which is intentionally more wasteful and slower but also helps in catching certain otherwise highly difficult to notice problems. When you gain more experience you can define your own shades of different Debug builds which trade speed for increased difficulty in debugging.

But whatever you do, debug builds are not intended to evaluate their performance. Someone who knows what what they are doing and what they intend to debug with it can setup a debug configuration which is going to be almost as fast as the optimized release build. You still do not profile it, you still do make assumptions about the efficiency based on debug builds.

#5300657 Overall Strategy For Move-Semantics? [C++11]

Posted by on 14 July 2016 - 12:32 AM

When I am in this situation (which does not happen really often) I have tried a few approaches since C++11 and ended up settling on (4).

I don't think thePyro_13's approach is useful though because it pretty much throws type safety out the window and prevents you from hiding any implementation details in its own compilation unit. It's obviously fine when you already write generic template code but I cannot see it work reasonably for the concrete stuff.

#5300529 How to automate texture deleting?

Posted by on 13 July 2016 - 07:52 AM

First: Bitmaster, basically what you mean is that in my code the 'for' loop calls textures.size() every time ''i'' is incremented, so I better assign a variable 'length' to it, this way I call the size() function only once and cut some operations. It's a small detail, but important, thanks for the quick answer.

The call is actually not that bad because the compiler can trivially inline and remove it. The problem is the compiler is not allowed to do more interesting things with the value, like moving it directly into a register. 


Two things. First, you do not want
void Tile::draw( App app )
because that will copy the content of App. That will either break your code or be horribly expensive. Quite possibly both. You want a call by reference
void Tile::draw(App& app)
or calling it with a pointer
void Tile::draw(App* app)
Second, you have a circular dependency. There will be many places around the web explaining the details and how to fix it, for example this one.

#5300519 How to automate texture deleting?

Posted by on 13 July 2016 - 07:20 AM

Edit: Unfortunately several posts were added while I was typing this up. When I say "That's certainly one way to go" I was referring to #6, not a map. A map would be rather pointless here.

That's certainly one way to go but you could also take this opportunity to look at some different syntax which offers some minor benefits.

When you do
for (std::size_t i = 0; i < container.size(); ++i)
you are making the compilers job unnecessarily complicated and force it to generate sub-par code. You can do better with
for (std::size_t i = 0, length = container.size(); i < length; ++i)
because now the compiler use the aliasing rules to its advantage. It's still better to use iterators like
for (auto it = container.begin(), last = container.end(); it != last; ++it)
because that turns into something much simpler after the optimizer got its hands on it. When you go
for (const auto& element : container)
you do pretty much that while being less verbose.

While talking about these things for the destruction of a couple of textures is obviously of limited use the basic problem (iterating over some kind of container) is something we do a lot in games. And shaving off a few cycles in inner loops can mean the difference between a smooth display or not. Especially if this also makes loops more readable.

#5300509 How to automate texture deleting?

Posted by on 13 July 2016 - 06:40 AM

I don't know what you've written here, but maybe I will create a vector, then push_back all the textures in that vector and then clear the whole vector.
But thanks for the answer.

No, that is not enough if you need to call something like destroyTexture. I have simply written a ranged for-loop which iterates over all elements in a container (for example an std::vector) and calls destroyTexture on that element and then empties the container.

#5300503 How to automate texture deleting?

Posted by on 13 July 2016 - 06:09 AM

What about just
for (auto texture_name : my_container_of_texture_names)