模板类是否可以相互依赖,前提是它们不尝试存储彼此的实例?



我正在尝试一些简单的基于模板的设计工作,并偶然发现了模板相互依赖性。现在我知道我可以使用虚拟函数和(在这种特定的人工情况下)通过将 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对我来说很好。

鉴于您使用的语法,您要做的事情是不可能的。

也就是说,在将适当的参数传递给模板之前,MySocket作为类型不存在。

由于MySocket依赖于MyHandler,而又取决于你有一个循环依赖MySocket,所以这是行不通的。

我怀疑您随后试图通过将MySocket作为类型名来向前声明来解决此问题,这C++无效。

不过,有一种方法可以解决此问题,那就是使用模板模板参数

模板模板参数允许您将另一个模板作为参数传递给模板

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

这里SocketT是一个模板本身,采用 1 个模板参数(因此名称模板模板参数)

EventHandlerT,您可以定义一个具体类型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;
}

最新更新