::运算符在这种情况下会做什么

tud*_*ion 3 c++ templates static-methods template-meta-programming

template <int N>
struct Factorial {
  static const int value = N * Factorial<N - 1>::value;
};

// Base case via template specialization:

template <>
struct Factorial<0> {
  static const int value = 1;
};
Run Code Online (Sandbox Code Playgroud)

因此,我可能已经发现,“ ::”运算符的作用是以某种方式将较早执行的操作的内容(N *阶乘)馈入/添加到“值”变量中。但是有人可以更彻底地解释这一点吗(我不介意对'::'运算符角色的完整解释)。

非常感谢你!

Edw*_*rak 6

::运算符称为范围解析运算符。它“解析”或明确了右侧操作数(变量名)所在的范围。

例如,std::cout使编译器清楚知道cout应该在namespace中搜索标识符std。在您的情况下,请Factorial<N - 1>::value明确说明它value是templated类的成员Factorial<N - 1>。在这里使用它是因为valuestatic类的一个字段。


Use*_*ess 6

所以我可能已经发现

我强烈建议从书中学习 C ++,并学习使用现有的参考资料,而不是试图从基本原理中弄清楚某些代码的含义。如果您进行有根据的猜测,很可能会犯一些细微的错误。

该表达式Factorial<N - 1>::value是一个合格的标识符

Factorial<N - 1>是类的名称(具有Factorial<int>单个参数特定值的模板实例化)。此类具有名为的数据成员value。需要明确的资格证明,因为此特殊 value情况不在范围之内。另请参阅限定名称查找

您可以::对任何类成员使用这样的方法:例如,std::string::npos粗略地表示在名为的命名空间中的类中找到被调用的数据成员nposstringstd

...以某种方式将先前执行的操作的内容馈入/添加到'value'变量中...

没有“较早的版本”,所有这些都发生在编译的同一阶段。

例如,我可以手动编写

struct F_0 { static const int value = 1; }
struct F_1 { static const int value = 1 * F_0::value; }
struct F_2 { static const int value = 2 * F_1::value; }
struct F_3 { static const int value = 3 * F_2::value; }
Run Code Online (Sandbox Code Playgroud)

等等等等,以获得我想要的尽可能多的值。模板化版本实际上是相同的,但是节省了大量输入。

具体而言,写作Factorial<3> 实例化模板Factorial<int N>N=3,这意味着我们现在有一个具体的非模板类Factorial<3>相当于F_3我写上面的手动。

此类的定义引用Factorial<N-1>::value(带有N-1 = 2),因此也Factorial<2>被实例化。隐式实例化链将一直持续到我们达到显式专用化为止Factorial<0>(否则,它将一直尝试实例化Factorial<-1>,,Factorial<-2>直到编译器放弃并失败为止)。