To make it short visual studio 2017 crashes when I am compiling this file:
#pragma once
/// @file
/// @brief Class mbe::HandleBase
#include <unordered_map>
//#include <cassert>
namespace mbe
{
template <class Derived>
class HandleBased abstract
{
public:
typedef unsigned long long int HandleID;
public:
HandleBased();
~HandleBased();
// Maybe rename to GetHandleId()?
HandleID ThisHandleId();
/*{
return id;
}*/
// Maybe rename to FindHandledObject
static Derived * FindPtr(HandleID id)
{
auto it = HandleBased::GetMap().find(id);
if (it == HandleBased::GetMap().end())
return nullptr;
// Should always be save
//assert(dynamic_cast<Derived *>(it->second));
return static_cast<Derived *>(it->second);
}
private:
static HandleID NextHandle()
{
// Every handle will get its own unique id
static HandleID next = 0;
return next++;
}
static std::unordered_map<HandleID, HandleBased *>& GetMap()
{
// Create the static map which will be used to keep track of the Derived handles and their ids
static std::unordered_map<HandleID, HandleBased *> map;
return map;
}
private:
HandleID id; // The id of this handle object
};
#pragma region Template Implementation
template<class Derived>
HandleBased<Derived>::HandleBased() :
id(NextHandle())
{
HandleBased::GetMap()[id] = this;
}
template<class Derived>
HandleBased<Derived>::~HandleBased()
{
auto it = HandleBased::GetMap().find(id);
HandleBased::GetMap().erase(it);
}
template<class Derived>
inline HandleID HandleBased<Derived>::ThisHandleId()
{
return id;
}
#pragma endregion
} // namespace mbe
It compiles fine when the ThisHandleId()
function is defined directly below its definition. Is something wrong with my template implementation? I have noticed that the HandleID typedef does not show up in intellisense.
Sometimes VS crashes completely (goes grey and windows displays the message: "Visual Studio 2017 stopped working". Sometimes it just shows that ingame message: "C/C++ optimising compiler stopped working"
Furthermore, I get a ton of compile errors when defining the other functions beneath the HandleBase class or in an inline file. As I said, everything compiles just fine if all functions are implemented just beneath their definition. I have also experimented with removing inline which avoids the crash but gives me even more compile errors. Mosty complete non-sense such as:
2>c:\users\adrian\documents\visual studio 2017\projects\mars base engine ecs 5\mars base engine ecs\handlebase.h(75): warning C4346: "ThisHandleId": Abhängiger Name ist kein Typ
2>c:\users\adrian\documents\visual studio 2017\projects\mars base engine ecs 5\mars base engine ecs\handlebase.h(76): note: Präfix mit "typename" zum Angeben eines Typs
2>c:\users\adrian\documents\visual studio 2017\projects\mars base engine ecs 5\mars base engine ecs\handlebase.h(76): error C2988: Unerkannte Vorlagendeklaration/-definition
2>c:\users\adrian\documents\visual studio 2017\projects\mars base engine ecs 5\mars base engine ecs\handlebase.h(76): error C2059: Syntaxfehler: ""
2>c:\users\adrian\documents\visual studio 2017\projects\mars base engine ecs 5\mars base engine ecs\handlebase.h(76): error C2143: Syntaxfehler: Es fehlt ";" vor "{"
2>c:\users\adrian\documents\visual studio 2017\projects\mars base engine ecs 5\mars base engine ecs\handlebase.h(76): error C2447: "{": Funktionsheader fehlt - Parameterliste im alten Stil?
Sorry for the German comments, but u can probably guess what some of them meen. There is stuff like 'depended name is not a type', 'syntax error ""' and 'missing an ; before {'
Also, I don't think removing the inline is a good idea in the first place.
In case you are wondering what the code is for, its described in the acceted answer of this stack overflow question: Using shared_ptr for unique ownership (kind of) - is this good practice?
Hope you can help me with this weird occurence....
Thanks, Adrian
HandleID
is a scoped type. Hence, you will need to use HandleBased<Derived>::HandleID
. Furthermore, since HandleID
is a dependent type. Hence, you will need to use typename HandleBased<Derived>::HandleID
.
Use:
template<class Derived>
inline typename HandleBased<Derived>::HandleID HandleBased<Derived>::ThisHandleId()
{
return id;
}
Alternatively, use trailing return type (Thanks are due to @Angew):
template <class Derived>
auto HandleBase<Derived>::ThisHandleId() -> HandleId
{
return id;
}
That works since trailing return types are within the scope of the class.