There are some things here to be improved:
Order your
#include
s alphabetically. This will facilitate checking whether all required#include
s are there. Also, consider leaving a space between#include
and<...>
as this tends to be a coding style issue most programmers agree on. Also, you don't seem to use anything fromfuture
, so you should remove it.//evil? yes. acceptable for readibility of post? yes.
No, I disagree. You're putting your code up for review here, so you should be posting your real code and not some changed variant that will never actually see a compiler. Usingusing namespace std;
or not can mean the differences between subtle bugs that may not manifest until some edge case occurs, and you'd probably want to be told about those in a code review. Also, in all honesty, writingstd::
every few lines doesn't change the length of your code much at all.It is discouraged nowadays to use
#define
for simple numeric constants. You could either useenum class
here (or, if you don't have anything >=C++11,enum
) or define constants.Again, if you have C++11 or beyond available, you should prefer
using
totypedef
, because it is much more readable and versatile.Being explicit is good, but being too explicit is bad, too.
unsigned int
can be written asunsigned
, which is most commonly used today. Ultimately, though, this is a personal style issue, so don't take this point as a required change.int
is not the right type for everything. For example,for (int i = 0; i<distanceGrid.size(); i++)
might overflow becausedistanceGrid.size()
might be bigger thanint
and, in any case, unsigned. The standard offersstd::size_t
for sizes, so you should make use of it where appropriate.Don't use
std::endl
because it's horrible. Although it does insert an endline character into the output stream, it also flushes the underlying buffer which is very rarely required (and for that cases there isstd::flush
) and can seriously harm performance if you're doing a lot of IO. Just write'\n'
instead, the underlying system takes care of converting it to the correct end-of-line sequence for the current OS.Use member initialization lists where possible. Lines such as
worldMinExtents = worldMinExt;
should just be part of the member initialization list of your constructor.Your code violates the Single Responsibility Principle. To be exact,
distanceFieldGrid
is doing not only its main purpose but also IO, which violates its responsibility. Extract the IO to a helper class/function so that other people can usedistanceFieldGrid
without getting extremely annoyed at standard output they don't want. The same is true for benchmarking: You shouldn't have a methoddoPathfind
that measures time, but write a separate benchmark class/function, possibly utilizing a benchmark library that allows you to get more reliable results.setPassable
should take its first argument byconst&
. Currently, you're making a copy ofgridPos
every single time, but don't do anything with it that would change its contents. Taking the parameter by reference to const will remove that copy and thus speed up the code (probably).nextNeighbours.emplace_back(std::piecewise_construct, forward_as_tuple(currentNeighbours[i].first - 1), forward_as_tuple(currentNeighbours[i].second));
is a lot of code that does remarkably little.std::piecewise_construct
is very handy in some cases, but this is definitely not one of them. Just writenextNeighbours.emplace_back(currentNeighbours[i].first - 1, currentNeighbours[i].second)
, or just usepush_back
(std::pair<unsigned, unsigned>
is not exactly what you would call expensive to copy).Don't make assumptions about the container type everybody uses. Instead of taking a
std::vector
or astd::list
or any other container as a function parameter, take a begin and an end iterator instead. Iterators enable the caller to use whatever container he wants while not putting a huge burden on the library implementer to ensure correctness for every available container type.//a smaller grid to test correctness
The keyword here is test. You should restructure your project and write actual tests and benchmarks for correctness and performance. Themain
function is not the right place to do any of those.Since we are talking about restructuring your project: Nearly all of your code should be extracted into a header and an implementation file.
vector<uiVec2d>({ make_pair(3,4), make_pair(2, 4), /* many, many more elements */})
is terrible to read and verify. You should have a separate object definition, maybe even a dedicated generator function (in the test class this actually belongs to, of course).
You said that your code has a lot stripped out. However, if you really want us to help you, you should restructure your code into multiple smaller units and ask for review of each of these units alone. As is, your code may be big and bulky, but refactoring can help to limit the scope of functionality for certain classes and make effective code review possible.