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

时间:2017-05-14 13:32:26

标签: c++ templates

我试图让一些简单的基于模板的设计工作,并偶然发现模板相互依赖。现在我知道我可以使用虚函数和(在这个特殊的人工案例中)通过将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对我来说很好。

1 个答案:

答案 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}}