【问题标题】:How can I make GCC and VS compilers agree on `typename` keyword?如何让 GCC 和 VS 编译器就 `typename` 关键字达成一致?
【发布时间】:2021-11-14 09:26:23
【问题描述】:

当我忽略输入 typename 关键字时,是否可以更改 Visual Studio (2019) 构建设置以使下面的第一行无法编译。因为 GCC 一直抱怨它是必需的,没有它就无法构建。

auto v = std::dynamic_pointer_cast<T::element_type>(sp);         // Builds in VS, fails in GCC
auto v = std::dynamic_pointer_cast<typename T::element_type>(sp);// Builds in both VS and GCC

注意:

  • spshared_ptr&lt;Base&gt;
  • Tshared_ptr&lt;Derived&gt;
  • Derived 派生自 Base

我已经将 VS 语言标准设置为 C++17 (/std:c++17),警告级别设置为 4 (/W4) 并开启了完全兼容性 (/permissive-)。但是 Visual Studio 仍然允许这条线通过。由于缺少typename,GCC(版本 10.3 设置为 C++17)将无法编译

我不在乎哪个编译器对仍然需要的关键字是正确的。关键是它是合法的,不管它是不是多余的。如果可能的话,我只是想通过构建开关强制他们就该主题达成一致。

另外,如果根据未来的 C++ 17 标准不再真正需要该关键字,那么我是否可以翻转 GCC 构建设置以允许代码行在没有关键字的情况下通过?

[编辑]

我在这里添加了一个最小的可重现示例。很抱歉最初没有把它放进去,但我主要是要求编译器标志或其他东西,所以我认为没有必要。以下代码使用我提到的编译器设置在 VS 2019 16.11.3 上构建得很好。诚然,这是人为的,但我根据实际代码改编了它,这非常多毛……

#include <stdexcept>
#include <type_traits>
#include <memory>

class Base
{
public :
    Base() {}
    virtual ~Base() {}
};

using BasePtr = std::shared_ptr<Base>;

class Derived : public Base
{
};

using DerivedPtr = std::shared_ptr<Derived>;

template<class T> 
typename std::enable_if<std::is_convertible<T, BasePtr>::value, T>::type
getAsT(BasePtr sp)
{

    const auto out = std::dynamic_pointer_cast<T::element_type>(sp); 

    if (nullptr == out)
        throw std::runtime_error("Not the right type");

    return out;
}
int main()
{
    auto derived = std::make_shared<Derived>();
    auto derived2 = getAsT<DerivedPtr>(derived);
}

【问题讨论】:

  • // Builds in both VS and GCC 有什么问题?
  • 您是否已经检查过 clang 在这方面的表现? (我不知道它是否与 gcc 一起使用。)因此,您可以在签入之前添加一个带有 clang 的工具链,以便在 Windows/Visual Studio 中进行检查。(我不知道更好的工作流程。我是曾经在虚拟机中检查我在 Debian 中的代码库,但和你一样,我经常忘记这样做之前提交...)
  • @463035818_is_not_a_number 是的。使 MSVC 抱怨的 MSVC 标志或使 GCC not 抱怨的 GCC 构建标志。只要语言合法
  • 尝试编译使用/Za标志? docs.microsoft.com/en-us/cpp/build/reference/…
  • @Joe Compiler Explorer 是一个方便的工具,可以解决像您这样的问题。 (我曾经用它来了解MSVC的/permissive-选项的意义:Compiler Explorer: Conformance Test。);-)

标签: c++ visual-studio gcc c++17


【解决方案1】:

我没有可供试用的 Visual Studio 副本,因此我将提出一些通用建议。 (不要对我大喊大叫,我只是想帮忙)

首先,这可能不是编译器应该处理的事情。可以使用静态分析器进行语言检查。 Visual Studio 有一个内置的静态分析器。您可以尝试打开它并按照说明搜索与“typename”相关的规则here

肯定会起作用的类似技术是安装“clag-tidy”plug-in for visual studio,其中有几个可供选择。一般来说,如果 clang-tidy 可以解析你的代码,GCC 也可以。 您通常可以将 clang-tidy 映射为在按键时运行,甚至在保存文件时运行。

对不起,如果这不够具体,但我希望它给你一些选择。

【讨论】:

  • 这是编译器应该处理的事情,因为迂腐typename是必需的
  • 根据 MS,“在模板定义中,向编译器提供了一个提示,即未知标识符是一种类型。”。它们可能是错误的,但提示很少暗示需要。当我发布我的建议时,我知道它会引起抨击,这就是为什么我说“不要对我大喊大叫”。哪个更容易?说服 MS 生成一个完美的编译器,或者使用静态分析器传递来执行与生成的代码无关的特定规则?我的回答具有实际有用的优点。 docs.microsoft.com/en-us/cpp/cpp/typename?view=msvc-160
  • Analyzer 没有抱怨我的代码,很遗憾。将看看clang-tidy。我不愿意为所有开发人员添加额外的构建步骤,所以看起来这可能是要走的路
  • 通俗地说它是一个“提示”,因为在许多情况下,原则上它可以被省略而不会产生歧义。尽管如此,它是必需的,如果忽略它是一个错误(我认为规则已经改变或将会改变,但直到 C++17 才知道)。
猜你喜欢
  • 2021-06-26
  • 2019-05-11
  • 1970-01-01
  • 1970-01-01
  • 2022-10-14
  • 1970-01-01
  • 2014-11-14
  • 1970-01-01
  • 2018-09-21
相关资源
最近更新 更多