模板化的格式错误的非模板化方法的实例化 class

Instantiation of ill-formed non-templated method of a templated class

我正在研究 two phase name lookup. A very logical explanation shows that one of the main reasoning,因为它遵循 尽早捕获错误的 C++ 哲学

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

例如:

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> 是非法的。

我认为第 (1) 行应该会产生错误,无论您是否曾调用 foo

在编写模板化 classes 时,这可能会让错误从裂缝中溜走,直到您最终调用该有问题的方法 (2),而不是在实例化模板化 class 时得到错误(1).

还有健全性检查:如果我实例化 X<int> (1) 但从不调用 X<int>::foo (2),代码是否有效?还是类似于 "ill-formed, no diagnostics required"?如果是后者,那么这是更早发现错误的更多理由。

代码有效。

此功能旨在允许 std::vector 具有简单的 operator<operator==

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

但如果您从未这样做过,vector 也可以正常工作。

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

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