2017-05-14 24 views
1

我試圖得到一些簡單的基於模板的設計工作,並偶然發現模板相互依賴。現在我知道我可以通過將EventHandler方法轉換爲模板而不是整個類來使用虛函數和(在這個特殊的情況下)來解決這個問題。但是有沒有辦法有兩個相互依賴的模板,只要它們互相使用指針?模板類可以互相依賴,只要它們不嘗試存儲對方的實例?

這簡化的示例:

typename MySocket; 

template<typename SocketClass> struct EventHandler { 
    void receiveCallback(SocketClass *s) { 
    } 
}; 

template <typename HandlerType> class Socket { 
    HandlerType *handler; 
}; 

typedef EventHandler<MySocket> MyHandler ; 
typedef Socket<MyHandler> MySocket ; 

MyHandler h; 
MySocket socket; 

int main() { 
    return 0; 
} 

對於這個代碼編譯給出了一個錯誤,指出插座被重新定義。有任何想法嗎? C++ 11/14對我來說很好。

+0

什麼是很第一行應該這樣做? – DeiDei

+0

'typename MySocket;'是無效的C++。你應該得到一個錯誤。 –

+0

當然,我嘗試了A可以想到的任何東西。這意味着作爲一個前向聲明,事後明顯它是錯誤的。 –

回答

1

根據您使用的語法,您要做的事情是不可能的。

也就是說,MySocket作爲一種類型在您將適當的參數傳遞給模板之前不存在。

由於MySocket取決於MyHandler,而這又取決於MySocket你有一個循環依賴,所以這是行不通的。

我懷疑你然後試圖解決這個通過轉發宣告MySocket作爲一個typename,這是無效的C++。

有一種方法可以解決這個問題,那就是使用template template parameters

模板模板參數讓你到另一個模板作爲參數傳遞給模板

template<template<typename> class SocketT> 
struct EventHandlerT; 

這裏SocketT是一個模板本身,服用1個模板參數(故名模板模板參數)

InsideEventHandlerT然後,您可以定義一個具體類型Socket,它使用EventHandlerT作爲模板參數,其中SocketT需要。

template<template<typename> class SocketT> 
struct EventHandlerT; 
{ 
    using Socket = SocketT<EventHandlerT>; // Socket is now a concrete type 
}; 

當你再要創建的Socket一個實例,您可以使用內部EventHandlerT

using EventHandler = EventHandlerT<SocketT>; 
using Socket  = EventHandler::Socket; 

下面是一個工作示例中定義的:

template<template<typename> class SocketT> 
struct EventHandlerT 
{ 
    using Socket = SocketT<EventHandlerT>; 

    void receiveCallback(Socket* s) 
    { 
    } 
}; 

template <typename HandlerT> 
struct SocketT 
{ 
    HandlerT* handler; 
}; 

int main() 
{ 
    using EventHandler = EventHandlerT<SocketT>; 
    using Socket  = EventHandler::Socket; 

    EventHandler handler; 
    Socket  socket; 

    socket.handler = &handler; 
    handler.receiveCallback(&socket); 

    return 0; 
} 
+0

謝謝,這正是我想要的。 –