explicit specialization in non-namespace scope or multiple definition przy kompilacji templatów

0

Witam
Prosze o pomoc bo nie mogę sobie poradzić z problemem czemu poniższy kod sie nie kompiluje.
Wywala się error: "explicit specialization in non-namespace scope" przy liniach (*)
Jak wywalę z klasy deklaracje specjalizacji templetów to wtedy mamy multiple definition issue.

HardwareTalker:

class HardwareTalker
{
public:
    HardwareTalker();
    virtual ~HardwareTalker();

    template <typename TRequest>
    bool send(const DPDMessage<TRequest> &req)
    {
//implemetacja
    }
    template <typename TRequest>
    CRFCtrl_UDPToken sendAndWaitForResponse(const DPDMessage<TRequest> &req)
    {
//implemetacja
    }
    template <typename TRequest>
    CRFCtrl_UDPToken sendAndWaitForResponse(const DPDMessage<TRequest> &req, const u32 timeout)
    {
//implemetacja
    }
};

HardwareTalkerMock.hpp:

class HardwareTalkerTemplateWrknd : public HardwareTalker
{
public:
    HardwareTalkerTemplateWrknd():HardwareTalker() {};
    virtual ~HardwareTalkerTemplateWrknd() {};

    template <typename TRequest>
    bool send(const DPDMessage<TRequest> &req)
    {
        HardwareTalker::send<TRequest>(req);
    }
    template <typename TRequest>
    CRFCtrl_UDPToken sendAndWaitForResponse(const DPDMessage<TRequest> &req)
    {
        HardwareTalker::sendAndWaitForResponse<TRequest>(req);
    }
    template <typename TRequest>
    CRFCtrl_UDPToken sendAndWaitForResponse(const DPDMessage<TRequest> &req, const u32 timeout)
    {
        HardwareTalker::sendAndWaitForResponse<TRequest>(req, timeout);
    }

//(*)
    template <> bool send(const DPDMessage<TransmitON_OFFResponse> &req);
    template <> CRFCtrl_UDPToken sendAndWaitForResponse(const DPDMessage<TransmitON_OFFResponse> &req);
    template <> CRFCtrl_UDPToken sendAndWaitForResponse(const DPDMessage<TransmitON_OFFResponse> &req,  const u32 timeout);
//(*)

    //TransmitON_OFFResponse
    bool sendTransmitOnOff(const DPDMessage<TransmitON_OFFResponse> &req) { return false; }
    CRFCtrl_UDPToken sendAndWaitForResponseTransmitOnOff(const DPDMessage<TransmitON_OFFResponse> &req) { return CRFCtrl_UDPToken(); }
    CRFCtrl_UDPToken sendAndWaitForResponseTransmitOnOff(const DPDMessage<TransmitON_OFFResponse> &req, const u32 timeout) { return CRFCtrl_UDPToken(); }
};

w HardwareTalkerMock.cpp:

#include "HardwareTalkerMock.hpp"
template <>
bool HardwareTalkerTemplateWrknd::send(const DPDMessage<TransmitON_OFFResponse> &req)
{
    return sendTransmitOnOff(req);
}
template <>
CRFCtrl_UDPToken HardwareTalkerTemplateWrknd::sendAndWaitForResponse(const DPDMessage<TransmitON_OFFResponse> &req)
{
    return sendAndWaitForResponseTransmitOnOff(req);
}
template <>
CRFCtrl_UDPToken HardwareTalkerTemplateWrknd::sendAndWaitForResponse(const DPDMessage<TransmitON_OFFResponse> &req,  const u32 timeout)
{
    return sendAndWaitForResponseTransmitOnOff(req, timeout);
}
1

template'y musisz definiowac w jednym pliku (najlepiej zrobic to w h/hpp)

1

w pierwszej kolejności wywal plik HardwareTalkerMock.cpp (template definiujemy w pliku nagłówkowym, jak napisał @fasadin wyżej). Błąd explicit specialization in non-namespace scope powodowany jest tym, że obie funkcje (*):

//(*)
    template <> bool send(const DPDMessage<TransmitON_OFFResponse> &req);
    template <> CRFCtrl_UDPToken sendAndWaitForResponse(const DPDMessage<TransmitON_OFFResponse> &req

należy zdefiniować poza klasą w następujący sposób:

template <> bool HardwareTalkerTemplateWrknd::send<TransmitON_OFFResponse>(const DPDMessage<TransmitON_OFFResponse> &req)
{

}

template <> CRFCtrl_UDPToken HardwareTalkerTemplateWrknd::sendAndWaitForResponse<TransmitON_OFFResponse>(const DPDMessage<TransmitON_OFFResponse> &req)
{

}

template <> CRFCtrl_UDPToken HardwareTalkerTemplateWrknd::sendAndWaitForResponse<TransmitON_OFFResponse>(const DPDMessage<TransmitON_OFFResponse> &req,  const u32 timeout)
{
   
}

ponadto w klasie HardwareTalkerTemplateWrknd brakuje Ci return w funkcji send, sendAndWaitForResponse, sendAndWaitForResponse.

0

Niestety teraz mam multipleDefinition issue:

class HardwareTalkerTemplateWrknd : public HardwareTalker
{
public:
    HardwareTalkerTemplateWrknd(HwRelLogger& _log):HardwareTalker(_log) {};
    virtual ~HardwareTalkerTemplateWrknd() {};

    template <typename TRequest>
    bool send(const DPDMessage<TRequest> &req)
    {
        return HardwareTalker::send<TRequest>(req);
    }
    template <typename TRequest>
    CRFCtrl_UDPToken sendAndWaitForResponse(const DPDMessage<TRequest> &req)
    {
        return HardwareTalker::sendAndWaitForResponse<TRequest>(req);
    }
    template <typename TRequest>
    CRFCtrl_UDPToken sendAndWaitForResponse(const DPDMessage<TRequest> &req, const u32 timeout)
    {
        return HardwareTalker::sendAndWaitForResponse<TRequest>(req, timeout);
    }

    //template <> bool send<TransmitON_OFFResponse>(const DPDMessage<TransmitON_OFFResponse> &req);
    //template <> CRFCtrl_UDPToken sendAndWaitForResponse<TransmitON_OFFResponse>(const DPDMessage<TransmitON_OFFResponse> &req);
    //template <> CRFCtrl_UDPToken sendAndWaitForResponse<TransmitON_OFFResponse>(const DPDMessage<TransmitON_OFFResponse> &req,  const u32 timeout);

    //TransmitON_OFFResponse
    bool sendTransmitOnOff(const DPDMessage<TransmitON_OFFResponse> &req) { return false; }
    CRFCtrl_UDPToken sendAndWaitForResponseTransmitOnOff(const DPDMessage<TransmitON_OFFResponse> &req) { return CRFCtrl_UDPToken(); }
    CRFCtrl_UDPToken sendAndWaitForResponseTransmitOnOff(const DPDMessage<TransmitON_OFFResponse> &req, const u32 timeout) { return CRFCtrl_UDPToken(); }
};

template <>
bool HardwareTalkerTemplateWrknd::send<TransmitON_OFFResponse>(const DPDMessage<TransmitON_OFFResponse> &req)
{  //ta linijke wskazuje na multiple definition issue
    return sendTransmitOnOff(req);
}
template <>
CRFCtrl_UDPToken HardwareTalkerTemplateWrknd::sendAndWaitForResponse<TransmitON_OFFResponse>(const DPDMessage<TransmitON_OFFResponse> &req)
{ //ta linijke wskazuje na multiple definition issue
    return sendAndWaitForResponseTransmitOnOff(req);
}
template <>
CRFCtrl_UDPToken HardwareTalkerTemplateWrknd::sendAndWaitForResponse<TransmitON_OFFResponse>(const DPDMessage<TransmitON_OFFResponse> &req,  const u32 timeout)
{  //ta linijke wskazuje na multiple definition issue
    return sendAndWaitForResponseTransmitOnOff(req, timeout);
}

Używam gcc jakby co ale z outputu niestety ciężko odczytać co z czym koliduje, jest tylko napisane że te 3 wyzej linijki są jako multiple definition, więc może chodzi o templejta.

0

Czy został dodany strażnik nagłówka? Cały kod klasy umieścić w pliku HardwareTalkerTemplateWrknd.hpp np. tak:

#ifndef HARDWARETALKERTEMPLATEWKRND_HPP
#define HARDWARETALKERTEMPLATEWKRND_HPP

// tutaj wstaw cały kod HardwareTalkerTemplateWrknd

#endif // HARDWARETALKERTEMPLATEWKRND_HPP
0

tak został. Nie ma to też nic wspólnego z klasą: HardwareTalker że tam jest definicja templejta, bo jak dałem w klasie HardwareTalkerTemplateWrknd zmiane metody z send na send2:

    template <typename TRequest>
    bool send2(const DPDMessage<TRequest> &req)
    {
        return HardwareTalker::send<TRequest>(req);
    }

i poza definicją klasy w tym samym pliku nagłówkowym:

template <>
bool HardwareTalkerTemplateWrknd::send2<TransmitON_OFFResponse>(const DPDMessage<TransmitON_OFFResponse> &req)
{
    return sendTransmitOnOff(req);
}

to dalej ten sam błąd z multiple definition. Tak jakby nie można było robić specjalizacji templejta, jakby kompilator na to nie pozwalał.
jeszcze też wyczyściłem całe przebudowanie i próbowałem skompilowac jeszcze raz ale bez powodzenia.
A specjalizacje templejtów są mi potrzebne jako workaround na mockowanie. Templejtów nie da się mockowac w google mocku przez to że nie da sie ich zwirtualizować, ale mając specjalizację już można gimnastykując się poradzić sobie z mockowaniem.

1

Wszystko jest prawie dobrze z tym, że zabrakło jeszcze jednej istotnej rzeczy, którą przeoczyłem w pierwszym poście. Błąd: multiple definition of (...) wynika z umieszczenia specjalizacji bezpośrednio w pliku nagłówkowym. Są na to dwa rozwiązania:

  1. specjalizacje uczynić inline (zostawiamy je w pliku nagłówkowym),
  2. specjalizacje przenieść do pliku źródłowego .cpp, a w pliku nagłówkowym zostawić jedynie ich deklaracje.
0

ok, teraz się kompiluje, także temat można zamknąć. Dzięki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1