尝试构建以下代码时出现链接错误

时间:2019-11-26 11:39:18

标签: c++

我正在用C ++实现一种事件机制(类似于C#中的事件)。我为此使用模板类。 当我尝试创建事件时,发生链接错误

ERROR:LNK2019   unresolved external symbol
 "public: __cdecl NS::Event<void __cdecl(class std::basic_string<char,struct std::char_traits<char>,
   class std::allocator<char> >)>

我的C ++代码如下所示。

'''EventManager.CPP

#include "EventManager.h"

using namespace NS;

template <class RetType, class... Args > struct Event<RetType(Args ...)> ::ComparableClosure
{
    Closure Callable;
    void* Object;
    uint8_t* Functor;
    int FunctorSize;

    ComparableClosure(const ComparableClosure&) = delete;

    ComparableClosure() : Object(nullptr), Functor(nullptr), FunctorSize(0) { }

    ComparableClosure(Closure&& closure) : Callable(std::move(closure)), Object(nullptr), Functor(nullptr), FunctorSize(0) { }

    ~ComparableClosure()
    {
        if (Functor != nullptr)
            delete[] Functor;
    }

    ComparableClosure& operator=(const ComparableClosure& closure)
    {
        Callable = closure.Callable;
        Object = closure.Object;
        FunctorSize = closure.FunctorSize;
        if (closure.FunctorSize == 0)
        {
            Functor = nullptr;
        }
        else
        {
            Functor = new uint8_t[closure.FunctorSize];
            std::memcpy(Functor, closure.Functor, closure.FunctorSize);
        }

        return *this;
    }

    bool operator==(const ComparableClosure& closure)
    {
        if (Object == nullptr && closure.Object == nullptr)
        {
            return Callable.target_type() == closure.Callable.target_type();
        }
        else
        {
            return Object == closure.Object && FunctorSize == closure.FunctorSize
                && std::memcmp(Functor, closure.Functor, FunctorSize) == 0;
        }
    }
};

template <class RetType, class... Args > struct Event<RetType(Args ...)> ::ClosureList
{
    ComparableClosure* Closures;
    int Count;

    ClosureList(ComparableClosure* closures, int count)
    {
        Closures = closures;
        Count = count;
    }

    ~ClosureList()
    {
        delete[] Closures;
    }
};




template <class RetType, class... Args > bool Event<RetType(Args ...)> ::addClosure(const ComparableClosure& closure)
{
    auto events = std::atomic_load(&m_events);
    int count;
    ComparableClosure* closures;
    if (events == nullptr)
    {
        count = 0;
        closures = nullptr;
    }
    else
    {
        count = events->Count;
        closures = events->Closures;
    }

    auto newCount = count + 1;
    auto newClosures = new ComparableClosure[newCount];
    if (count != 0)
    {
        for (int i = 0; i < count; i++)
            newClosures[i] = closures[i];
    }

    newClosures[count] = closure;
    auto newEvents = ClosureListPtr(new ClosureList(newClosures, newCount));
    if (std::atomic_compare_exchange_weak(&m_events, &events, newEvents))
        return true;

    return false;
}

template <class RetType, class... Args > bool Event<RetType(Args ...)> ::removeClosure(const ComparableClosure& closure)
{
    auto events = std::atomic_load(&m_events);
    if (events == nullptr)
        return true;

    int index = -1;
    auto count = events->Count;
    auto closures = events->Closures;
    for (int i = 0; i < count; i++)
    {
        if (closures[i] == closure)
        {
            index = i;
            break;
        }
    }

    if (index == -1)
        return true;

    auto newCount = count - 1;
    ClosureListPtr newEvents;
    if (newCount == 0)
    {
        newEvents = nullptr;
    }
    else
    {
        auto newClosures = new ComparableClosure[newCount];
        for (int i = 0; i < index; i++)
            newClosures[i] = closures[i];

        for (int i = index + 1; i < count; i++)
            newClosures[i - 1] = closures[i];

        newEvents = ClosureListPtr(new ClosureList(newClosures, newCount));
    }

    if (std::atomic_compare_exchange_weak(&m_events, &events, newEvents))
        return true;

    return false;
}

template <class RetType, class... Args > Event<RetType(Args ...)>::Event()
{
    std::atomic_store(&m_events, ClosureListPtr());
}

template <class RetType, class... Args > Event<RetType(Args ...)>::Event(const Event& event)
{
    std::atomic_store(&m_events, std::atomic_load(&event.m_events));
}

template <class RetType, class... Args > Event<RetType(Args ...)>::~Event()
{
    (*this) = nullptr;
}

template <class RetType, class... Args > void Event<RetType(Args ...)> ::operator -=(Closure f)
{
    ComparableClosure closure(std::move(f));
    while (true)
    {
        if (removeClosure(closure))
            break;
    }
}

template <class RetType, class... Args > void Event<RetType(Args ...)> ::operator +=(Closure f)
{
    ComparableClosure closure(std::move(f));
    while (true)
    {
        if (addClosure(closure))
            break;
    }
}

template <class RetType, class... Args > bool Event<RetType(Args ...)> ::operator==(nullptr_t nullpointer)
{
    auto events = std::atomic_load(&m_events);
    return events == nullptr;
}

template <class RetType, class... Args > bool Event<RetType(Args ...)> ::operator!=(nullptr_t nullpointer)
{
    auto events = std::atomic_load(&m_events);
    return events != nullptr;
}

template <class RetType, class... Args > void Event<RetType(Args ...)> ::operator=(nullptr_t nullpointer)
{
    while (true)
    {
        auto events = std::atomic_load(&m_events);
        if (!std::atomic_compare_exchange_weak(&m_events, &events, ClosureListPtr()))
            continue;

        break;
    }
}

template <class RetType, class... Args > void Event<RetType(Args ...)> ::operator =(const Event& event)
{
    std::atomic_store(&m_events, std::atomic_load(&event.m_events));
}

template <class RetType, class... Args > template <typename TObject> void Event<RetType(Args ...)> ::Bind(RetType(TObject::* function)(Args...), TObject* object)
{
    ComparableClosure closure;
    closure.Callable = [object, function](Args&&...args)
    {
        return (object->*function)(std::forward<Args>(args)...);
    };
    closure.FunctorSize = sizeof(function);
    closure.Functor = new uint8_t[closure.FunctorSize];
    std::memcpy(closure.Functor, (void*)&function, sizeof(function));
    closure.Object = object;

    while (true)
    {
        if (addClosure(closure))
            break;
    }
}

template <class RetType, class... Args > template <typename TObject> void Event<RetType(Args ...)> ::Unbind(RetType(TObject::* function)(Args...), TObject* object)
{
    ComparableClosure closure;
    closure.FunctorSize = sizeof(function);
    closure.Functor = new uint8_t[closure.FunctorSize];
    std::memcpy(closure.Functor, (void*)&function, sizeof(function));
    closure.Object = object;

    while (true)
    {
        if (removeClosure(closure))
            break;
    }
}

template <class RetType, class... Args > void Event<RetType(Args ...)> ::operator()()
{
    auto events = std::atomic_load(&m_events);
    if (events == nullptr)
        return;

    auto count = events->Count;
    auto closures = events->Closures;
    for (int i = 0; i < count; i++)
        closures[i].Callable();
}

template <class RetType, class... Args > template <typename TArg0, typename ...Args2> void Event<RetType(Args ...)> ::operator()(TArg0 a1, Args2... tail)
{
    auto events = std::atomic_load(&m_events);
    if (events == nullptr)
        return;

    auto count = events->Count;
    auto closures = events->Closures;
    for (int i = 0; i < count; i++)
        closures[i].Callable(a1, tail...);
}



'''

'''EventManager.h

#pragma once
#include <typeinfo>
#include <functional>
#include <stdexcept>
#include <memory>
#include <atomic>

namespace NS
{

    template <typename TFunc> class __declspec(dllexport) Event;

    template  <class RetType, class... Args> class __declspec(dllexport) Event<RetType(Args ...)> final
    {
    private:
        typedef typename std::function<RetType(Args ...)> Closure;

        struct ComparableClosure;


        struct ClosureList;


        typedef std::shared_ptr<ClosureList> ClosureListPtr;

    private:
        ClosureListPtr m_events;

    private:
        bool addClosure(const ComparableClosure& closure);


        bool removeClosure(const ComparableClosure& closure);


    public:
        Event();

        Event(const Event& event);

        ~Event();


        void operator =(const Event& event);

        void operator=(nullptr_t nullpointer);


        bool operator==(nullptr_t nullpointer);


        bool operator!=(nullptr_t nullpointer);

        void operator +=(Closure f);

        void operator -=(Closure f);


        template <typename TObject>
        void Bind(RetType(TObject::* function)(Args...), TObject* object);


        template <typename TObject>
        void Unbind(RetType(TObject::* function)(Args...), TObject* object);


        void operator()();

        template <typename TArg0, typename ...Args2>
        void operator()(TArg0 a1, Args2... tail);

    };

'''

我试图从另一个类实例化Event,如下所示。但是它在构建过程中显示错误。

如果我评论以下行,我可以毫无错误地进行构建。

'''
Event <void(string)> LogNotification;
'''

另外,如果我将代码放在EventManager.h和EventManager.cpp中的单个EventManager.h文件中,它将起作用。但这不符合我的要求。我需要将标头和cpp文件分开以隐藏代码。

0 个答案:

没有答案