Before you consider intrusive lists, in fact, before you consider almost any other data structure, try a vector. People grossly overestimate the cost of vector relocation while underestimating the benefits of cache coherency. Vector relocation is so cheap because all the bits are in the cache. You can relocate all the elements in a reasonably sized vector faster than you can dereference a pointer to somewhere in memo…
The only problem with std::vector is that you can only belong to one (unless you have a vector of pointers, but that almost negates the whole point). The way I've typically done this is by having one global "all entities" std::vector and then lists, maps or whatever for specific subsets. Usually, my "entity" object is little more than a container for behaviours so in reality its a little more complicated than that...
If you can own the objects in one by-value vector, that's even better, then traversing over them involves only address arithmetic on objects that are already probably in the cache.