【问题标题】:C++ simple template recursionC++ 简单模板递归
【发布时间】:2014-11-16 17:05:58
【问题描述】:

我很确定以下问题的解决方案非常标准,但我找不到合适的术语来搜索它。我有两个班级,比如说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;
}

现在,我如何告诉编译器没有像 SomeA&lt;SomeB&lt;SomeA&lt;SomeB&lt;Suprise_AnotherA&lt;...&gt;&gt;&gt;&gt;&gt; 这样的“惊喜”?

【问题讨论】:

  • 你的概念没有意义。
  • @CashCow:哪个概念?
  • 抱歉,C++中不能直接定义递归类型。
  • OP 试图做什么的概念
  • 谷歌模板模板参数

标签: c++ templates recursion


【解决方案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 的实例,以进行有效过滤。

【讨论】:

  • 对不起,我看起来不像你在问题中描述的那样。我的意思是SomeA 中的SomeB&lt;SomeA&gt; test; 是一个模板。它不是您想要的 SomeA&lt;SomeB&gt; 类型。
  • @Kostya:触摸!不过,我很确定它可以解决我的问题。如果我知道模板模板参数,我会以不同的方式提出问题。我确定有一个关于这个的 xkcd...
【解决方案2】:

让我们将一个相当笨拙的 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&lt;SomeB&gt; 这样申请,那将是非法的,因为 SomeB 不是 typename -- 它是 typename-&gt;typename。如果我能将 SomeB 应用到某些东西上就好了得到一个简单的类型...

哦!我如何像SomeB&lt;SomeA&gt; 一样应用它?不,这是非法的,因为SomeB 不是typename——它是typename-&gt;typename。如果我能将 SomeA 应用到某个东西上以获得一个简单的类型就好了……

哦!我如何像SomeA&lt;SomeB&gt; 一样应用它?不,这是非法的,因为SomeA 不是typename——它是typename-&gt;typename。如果我能将 SomeB 应用到某个东西上以获得一个简单的类型...

哦!我如何像SomeB&lt;SomeA&gt; 一样应用它?不,这是非法的,因为SomeA 不是typename——它是typename-&gt;typename。要是我能把SomeB 应用到某个东西上来得到一个简单的类型就好了……"

等等——你明白了。这与the liar paradox 等所有经典逻辑悖论非常相似。更正式地说,您想要做的事情称为impredicative definition

你猜怎么着? Type theory was invented by Bertrand Russel 正是为了消除不可预测性。

因此,您的意图不仅与使用 C++ 表达自己的能力相冲突,而且与类型论的基本思想相冲突。而且,按照我的口味,根本没有任何意义。就像骗子悖论一样。

【讨论】:

    猜你喜欢
    • 2015-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-10
    • 1970-01-01
    • 2013-10-28
    • 1970-01-01
    相关资源
    最近更新 更多