编译模板实现时VS 2017崩溃

时间:2017-11-20 19:23:17

标签: c++11 templates visual-studio-2017 inline

为了简化Visual Studio 2017在编译此文件时崩溃:

#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

ThisHandleId()函数直接定义在其定义之下时,它编译得很好。我的模板实现有问题吗?我注意到HandleID typedef没有显示在intellisense中。

有时VS完全崩溃(灰色并且Windows显示消息:“Visual Studio 2017停止工作”。有时它只显示游戏消息:“C / C ++优化编译器停止工作”

enter image description here

此外,在HandleBase类或内联文件中定义其他函数时,我遇到了大量的编译错误。正如我所说的,如果所有函数都在其定义之下实现,那么所有函数都可以正常编译。我还尝试了删除内联,以避免崩溃,但给了我更多的编译错误。 Mosty完全没有意义,例如:

2&gt; c:\ users \ adrian \ documents \ visual studio 2017 \ projects \ mars base engine ecs 5 \ mars base engine ecs \ handlebase.h(75):warning C4346:“ThisHandleId”:AbhängigerNameist kein Typ

2&gt; c:\ users \ adrian \ documents \ visual studio 2017 \ projects \ mars base engine ecs 5 \ mars base engine ecs \ handlebase.h(76):注意:Präfixmit“typename”zum Angeben eines Typs < / p>

2&gt; 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&gt; c:\ users \ adrian \ documents \ visual studio 2017 \ projects \ mars base engine ecs 5 \ mars base engine ecs \ handlebase.h(76):error C2059:Syntaxfehler:“”

2&gt; 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&gt; 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?

对于德国人的评论感到抱歉,但你可能会猜到他们中的一些评论。有像'依赖名称不是类型','语法错误“”和'缺少一个;在{'

之前

另外,我不认为首先删除内联是一个好主意。

如果您想知道代码的用途,请在此堆栈溢出问题的加入答案中对其进行描述:Using shared_ptr for unique ownership (kind of) - is this good practice?

希望你能帮我解决这个奇怪的问题......

谢谢, 阿德里安

1 个答案:

答案 0 :(得分:3)

HandleID是范围类型。因此,您需要使用HandleBased<Derived>::HandleID。此外,由于HandleID是依赖类型。因此,您需要使用typename HandleBased<Derived>::HandleID

使用:

template<class Derived>
inline typename HandleBased<Derived>::HandleID HandleBased<Derived>::ThisHandleId()
{
    return id;
}

或者,使用尾随返回类型(感谢@Angew):

template <class Derived>
auto HandleBase<Derived>::ThisHandleId() -> HandleId
{
   return id;
}

这是有效的,因为尾随返回类型在类的范围内。