模板实例化是解析 C++ 的一部分吗

Is template instantation part of parsing C++

我曾与某人讨论过有关解析 C++ 的问题。他说 C++ 必须在解析时实例化所有模板,而我认为情况并非如此。您可以简单地创建一个解析树,然后再进行模板实例化。

GCC 和 Clang 如何处理这个问题?

你的朋友是对的。模板必须被实例化,这就是编译器所做的。 [注1]

还有更简单的示例,但我手头有这个;它取自 this answer.

main 中第一行的解析依赖于 IsPrime 模板的实例化(不仅仅是解析)。正如所写,如果 IsPrime 的模板参数不是质数,它会产生语法错误;然而,将 () 更改为 (0) 将允许两种可能性都有效,但解析非常不同。 (使用复合模板参数,typen是一个简单的整型常量,typen<1>(0)是两个比较,等价于(typen < 1) > 0。)

并不是所有的例子都像这个例子那样做作。当我写它的时候,我试图提出一个不同的观点,即 C++ 程序的正确解析可能需要解决一个相当复杂的数学问题,比如确定一个大数是否是质数。这使 C++ 远远超出了上下文无关语言的领域。

template<bool V> struct answer { answer(int) {} bool operator()(){return V;}};

template<bool no, bool yes, int f, int p> struct IsPrimeHelper
  : IsPrimeHelper<p % f == 0, f * f >= p, f + 2, p> {};
template<bool yes, int f, int p> struct IsPrimeHelper<true, yes, f, p> { using type = answer<false>; };
template<int f, int p> struct IsPrimeHelper<false, true, f, p> { using type = answer<true>; };

template<int I> using IsPrime = typename IsPrimeHelper<!(I&1), false, 3, I>::type;
template<int I>
struct X { static const int i = I; int a[i]; }; 

template<typename A> struct foo;
template<>struct foo<answer<true>>{
  template<int I> using typen = X<I>;
};
template<> struct foo<answer<false>>{
  static const int typen = 0;
};

int main() {
  auto b = foo<IsPrime<234799>>::typen<1>(); // Syntax error if not prime
  return 0;
}

备注

  1. Ira Baxter 会说您可以使用 GLR 解析器找到所有可能的替代解析,而无需实例化模板,然后 select 在实例化后找到正确的解析。的确如此,但是在您知道哪个解析正确之前,恕我直言,解析还没有完成。