C++:模板参数循环依赖
这更像是一个最佳实践问题,而不是一个语言问题本身,因为我已经对 C++ 中常见的绊脚石有了一个有效的解决方案。
我正在处理模板参数替换中的典型循环依赖问题。我有以下一对类:
template<class X>
class A { /* ... */ };
template<class X>
class B { /* ... */ };
并且我想将每个类实例化如下:
// Pseudocode -- not valid C++.
A<B> a;
B<A> b;
也就是说,我想将A“绑定”到B,将B“绑定”到A。
我可以通过粗略的方式解决问题使用继承技巧进行前向声明:
class sA;
class sB;
class sA : public A<sB> { /* ... */ };
class sB : public B<sA> { /* ... */ };
但这会带来一系列问题,因为 sA
和 sB
并不是真正的 A
和 B< /代码>。例如,如果没有正确地将
A
的构造函数复制到 sA
中,或者以某种方式围绕代码进行闪闪发光的强制转换,我就无法调用 A
的构造函数。
我的问题是:处理这个问题的最佳实际方法是什么?有什么特别巧妙的解决方案来解决这个问题吗?
我同时使用 MSVC2008 和 G++,但欢迎使用具有特定于编译器的扩展的解决方案。
谢谢,
亚历克
This is more a best practice question than a language question in itself, since I already have a working solution to what seems to be a common stumbling block in C++.
I'm dealing with a typical cyclic dependency issue in template parameter substitutions. I have the following pair of classes:
template<class X>
class A { /* ... */ };
template<class X>
class B { /* ... */ };
and I want to instantiate each one as the following:
// Pseudocode -- not valid C++.
A<B> a;
B<A> b;
that is, I want to 'bind' A to B, and B to A.
I can solve the problem, in a gross way, through a forward declaration with inheritance trick:
class sA;
class sB;
class sA : public A<sB> { /* ... */ };
class sB : public B<sA> { /* ... */ };
but this brings in a set of problems, since sA
and sB
are not indeed A
and B
. For example, I cannot invoke A
's constructors without properly duplicating them into sA
, or somehow sparkling casts around the code.
My question is: what is the best practical way to deal with this issue? Any specially clever solution to this problem?
I am using both MSVC2008 and G++, but solutions with compiler-specific extensions are welcome.
Thanks,
Alek
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如前所述,处理此问题的最佳实用方法是重构 - 通过解耦打破依赖关系。
可能的选项包括:
当您的需求突然发生变化时,这也可以帮助您。假设您在某些情况下需要一个特殊的
服务器
- 它当然应该支持您已经编写的所有客户端,您不想重写它们。或者在某些情况下您需要一些特殊的客户端
...使用您的方法,这将需要重写两侧,而解耦方法只需编写您需要更改的一侧的修改版本即可。
例如,采用客户端的静态方法:
这里,
client
甚至不需要知道server
的具体类型 - 如果它没有成员函数add_job(job&)
或兼容的东西,编译将会失败。如果您想变得更正式,您可以研究静态断言和概念检查。
As mentioned, the best practical way to deal with this is to refactor - break the dependencies by decoupling.
Possible options include:
This also helps you whenever your requirements suddenly change. Suppose you need a special
server
in some cases - it should of course support all the clients you've already written, you don't want to rewrite them. Or you need some specialclient
s in some cases...With your approach this would require rewriting both sides, whith a decoupled approach its just a matter of writing a modified version of the side you need to change.
Taking e.g. the static approach with clients:
Here,
client
doesn't even need to know the concrete type ofserver
- if it doesn't have a member functionadd_job(job&)
or something compatible, compilation will simply fail.If you want to get more formal, you could look into static assertions and concept checks.
由于模板的类型命名了它的所有参数,因此不能有参数化的无限循环。
您可能(当然)只是试图同时向相反的方向发送信息。这没有问题,但是你不能将信息封装在提供实现的类中。
Since a template's type names all its parameters, you can't have an endless loop of parameterization.
You are probably (certainly) just trying to send information in opposite directions at the same time. There's no problem with that, but you can't encapsulate the information in the classes that provide implementation.