我试图让一些简单的基于模板的设计工作,并偶然发现模板相互依赖。现在我知道我可以使用虚函数和(在这个特殊的人工案例中)通过将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;
}
对于此代码,编译器会给出一个错误,指出Socket已重新定义。有任何想法吗? C ++ 11/14对我来说很好。
答案 0 :(得分:1)
根据您使用的语法,您无法做的事情是不可能完成的。
也就是说,MySocket
作为一种类型并不存在,直到您将适当的参数传递给模板。
由于MySocket
取决于MyHandler
,而MySocket
依赖于MySocket
,因此您获得了循环依赖,因此无法正常工作。
我怀疑你接着尝试通过将template<template<typename> class SocketT>
struct EventHandlerT;
声明为SocketT
作为类型名来解决这个问题,这不是有效的C ++。
有一种方法可以解决这个问题,那就是使用 template template parameters 。
模板模板参数允许您将另一个模板作为参数传递给模板
EventHandlerT
此处Socket
是一个模板本身,带有1个模板参数(因此名称为模板模板参数)
在 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;
}
{{1}}
以下是一个工作示例:
{{1}}