我非常确定以下问题的解决方案非常标准,但我找不到合适的搜索条件。我有两个课程,比如SomeB<A>
和SomeA<B>
。我想创建SomeB<A>
A:=SomeA<B>
和B:=SomeB<A>
的实例。 (简化)代码如下所示:
template<typename A>
class SomeB
{
A getA() { /* ... */ }
};
template<typename B>
class SomeA
{
B getB() { /* ... */ }
};
int main(int argc, char **argv)
{
SomeA<SomeB<SomeA<SomeB<...> > > > test;
// /\
// |
// +---- recursion
test.getB();
return 0;
}
现在,我如何告诉编译器没有&#34;惊喜&#34;比如SomeA<SomeB<SomeA<SomeB<Suprise_AnotherA<...>>>>>
?
答案 0 :(得分:1)
感谢Vittorio Romeo向我指出了模板模板参数。这个编译和工作:
template<template<typename> class A>
class SomeB
{
public:
A<SomeB> getA() { return A<SomeB>(); }
};
template<typename B>
class SomeA
{
public:
B getB() { return B(); }
};
int main(int argc, char **argv)
{
SomeB<SomeA> test;
test.getA();
return 0;
}
有趣的人的元信息:SomeB是树(节点)类,SomeA是查找树中节点的特定子节点的类。 SomeA可以用许多不同的方式实现,它可以使用自己的数据结构来存储子节点,即SomeB的实例,以便进行有效的过滤。
答案 1 :(得分:0)
让我们将一个相当笨拙的C ++符号改为更类型理论(ish),以便我们可以尝试清楚地定义你想要的东西。
template<typename A> class SomeB { ... };
实际上意味着你有一个名为SomeB
的东西,它接受一个简单类型并返回另一个简单类型:
SomeB : typename -> typename
并且,例如,如果你有“模板模板参数”之类的东西:
template<template<typename> class A> class SomeB { ... };
那么这将转化为:
SomeB : (typename -> typename) -> typename
现在我知道你想要什么。你说“我这里有两个人”
SomeA : typename -> typename
SomeB : typename -> typename
“如果我想申请像SomeA<SomeB>
一样非法,因为SomeB
不是typename
- 它是typename->typename
。如果只有SomeB
。我将SomeB<SomeA>
应用于某些内容以获得简单类型...
哦!我应用SomeB
怎么样?不,这是违法的,因为typename
不是typename->typename
- 它是SomeA
。如果我只能将SomeA<SomeB>
应用于某些内容以获得简单类型...
哦!我应用SomeA
怎么样?不,这是违法的,因为typename
不是typename->typename
- 它是SomeB
。如果我只能将SomeB<SomeA>
应用于某些内容以获得简单类型...
哦!我应用SomeA
怎么样?不,这是违法的,因为typename
不是typename->typename
- 它是SomeB
。如果我只能将{{1}}应用于某些内容以获得简单类型... “
等等 - 你明白了。这与the liar paradox等所有经典逻辑悖论非常相似。更正式地说,你想做的事情叫做impredicative definition。
猜猜是什么?伯特兰·罗素(Bertrand Russel)Type theory was invented正是为了消除不信任。
所以你的意图不仅仅是与使用C ++表达自己的能力的冲突,它与类型理论的基本思想相冲突。而且,根据我的口味,根本没有任何意义。就像骗子悖论一样。