【问题标题】:VS2017 compiles code that is syntactically incorrect, Intellisence missingVS2017 编译代码语法错误,缺少智能感知
【发布时间】:2017-11-02 16:04:20
【问题描述】:

我从 VS2017 工作中获得了这种奇怪的行为,赢得了 C++ 项目: 缺少智能 - 我只是输入没有警告的纯文本,它仍然可以编译:

整个文件中没有显示错误。但是,当我在此函数范围之外的任何地方尝试相同的操作时,一切都按预期工作:

问题出现在我的泛型函数实现中:

#pragma region Public API
template <typename Key, typename Value>
void BinarySearchTree<Key, Value> ::Put(Key key, Value val)
{
    Node node = root_;
    if(node.key == null)
        sadadasd
        affsa
        dasds
        dasdsad
        asdsad
}

#pragma endregion

类定义如下:

template <typename Key, typename Value>
class BinarySearchTree {};

再一次,它是死寂的——根本没有红色/黄色。编译后的代码甚至可以运行。就好像那部分被注释掉了。

尝试重新加载VS,没有帮助

【问题讨论】:

  • 您实际上是在代码中的任何位置实例化此模板吗?
  • @Ron 我可以把它放到 main 中,例如:BinarySearchTree&lt;int, int&gt; bst; 没有错误
  • 模板代码中的错误会延迟到模板展开。当然,这从未发生过。
  • 我不知道为什么每个人都将实例化带入其中。模板在实例化之前仍会检查语法错误,并进一步检查不依赖于模板参数的部分。这是一个 MSVC 错误,当它们完全支持两阶段查找时可能会得到修复。
  • 如果有人想知道,大规模的反对票就是我。我对任何暗示这种行为是正确的人投了反对票(到目前为止,每个人都是如此)。

标签: c++ compilation visual-studio-2017 intellisense compiler-warnings


【解决方案1】:

这是一个长期存在的 Visual C++ 已知问题。它不实现两阶段查找。它基本上只是完全跳过模板,直到它们被实例化。显然,他们最终修复了它(至少部分修复)。

https://blogs.msdn.microsoft.com/vcblog/2017/09/11/two-phase-name-lookup-support-comes-to-msvc/

【讨论】:

【解决方案2】:

根据class template参考:

类模板本身不是类型、对象或任何其他 实体。不会从仅包含的源文件生成代码 模板定义。为了让任何代码出现,模板必须 被实例化...

更新:这似乎是 Visual C++ 特定的错误。其他编译器可能会报错。
Trivial example for GCC

此 SO 帖子中有关该主题的更多信息:
What exactly is "broken" with Microsoft Visual C++'s two-phase template instantiation?

【讨论】:

    【解决方案3】:

    类模板实例化 类模板本身不是类型, 或对象,或任何其他实体。 没有从源代码生成 仅包含模板定义的文件。为了让任何代码 出现,必须实例化模板:模板参数必须 提供,以便编译器可以生成一个实际的类(或 函数,来自函数模板)。

    【讨论】:

      【解决方案4】:

      模板仅在实例化时编译成二进制文件。如果不使用模板,代码就扔掉了

      【讨论】:

        【解决方案5】:

        在您使用带有参数的模板之前,它不会被实例化,因此它不会存在,因此不会出现错误。

        【讨论】:

        • 是的,错误会在构建时显示,并实例化一个成员....但是你是在告诉我,我必须构建解决方案来检测模板实现中的语法错误,而且我没有得到任何智能一直在写?
        • 一般来说,在不知道模板参数之前,检查模板的正确性是没有用的。因为模板可能允许你调用T.dance();之类的东西,在你知道T是否有函数dance()之前你无法检查它是否正确
        • @Arkady,正如 OP 的担忧所表明的那样,尽早检查正确性并不是没有用的。在编写模板而不是在测试模板时会发现大量错误(或者更糟糕的是,您没有编写测试并且在发布后出现问题)。该标准规定了哪些部分需要稍后处理。
        • @chris,将其视为任务。你需要创建一个非常聪明的检查系统,对于像T.sdfsd这样的困难情况,在你知道T是什么之前,它是否有成员sdfsd,如果不使用就没有人需要它。但由于只有某人在使用它,您可以免费获得所有用例变体的全面检查。所以,没有理由解决这个问题。很高兴拥有它,但我认为这绝对不是什么重要的事情。这就是为什么它在 VS 中寿命如此之长
        • @Arkady,这就是T.sdfsd 延迟的原因。您延迟依赖模板参数的事情并检查不依赖的事情。但这不是一个理想的。这就是 C++ 的指定方式。编译器必须做到这一点,而 MSVC(目前)还没有。
        最近更新 更多