实例化模板类的格式化非模板化方法

时间:2016-09-28 14:42:26

标签: c++ templates instantiation

我正在研究two phase name lookup。一个非常合乎逻辑的解释表明one of the main reasoning就是遵循C ++哲学尽早发现错误

我的问题是为什么这种哲学不是非模板化的方法。而不是检查何时以及是否调用该方法,为什么不在实例化模板化类时检查阶段2中的所有非模板化方法?

E.g:

template <class T>
struct X {

  auto foo() // non-templated (important)
  {
    T t{};
    return t.non_existing();
  }
};

int main()
{
  X<int> x; // (1) this compiles OK.

  // somewhere is a galaxy far far away,
  // maybe deep inside some unrelated code
  x.foo();  // (2) the error is here
}

如果你从不写(2)程序编译并运行没有任何问题,虽然foo对于实例化的X<int>是非法的。

我认为无论你是否曾致电foo,行(1)都会产生错误。

在编写模板化类时,这可以让错过错误,直到最后调用有问题的方法(2),而不是在实例化模板化类(1)时得到错误。

同样健全性检查:如果我实例化X<int>(1)但从不调用X<int>::foo(2),代码是否有效?或者它是什么样的&#34;形成不良,不需要诊断&#34;?如果是后者,那么这是更早发现错误的理由。

1 个答案:

答案 0 :(得分:6)

代码有效。

此功能旨在允许std::vector之类的内容只是operator<operator==

此操作符会盲目地尝试在其元素上调用<==。如果它无效,一旦您在包装<上调用==vector,它将无法编译。

但如果你从未这样做过,那么vector就行了。

现代C ++建议使用SFINAE条件方法技术或C ++ 20 Requires子句,因此vector只有 ==<是一个有效的操作。在设计vector时,这些技术都不成熟,并且能够使模板类的方法无效是一个重要特征。

除了无效代码的早期失败之外,有条件地存在==允许包装代码以检测==是否可以安全地调用:古老的技术不允许这种内省。我不得不编写专门用于标准容器模板的自定义特征,以检测<是否可以安全地调用至少一个案例。