c++ - 如何在不更改所有代码以使用 this-> 的情况下避免旧模板重库中的 'not declared' 错误?

标签 c++ templates gcc legacy-code

尝试编译包含大量模板化代码的库时出现“未在此范围内声明”错误。代码似乎是使用 gcc-2.95 开发的,并且(据我所知)大约四年前编译过。正如我在 StackOverflow 上发现的那样和 C++-FAQ代码确实预计会失败,并且似乎依赖于不符合规范的编译。

最小复制示例,用gcc -c example.cpp编译:

// file: example.cpp
template <typename T>
class Base {
  protected:
    int i;
};

template <typename T>
class Derived : protected Base<T> {
  public:
    void f() {
        // i = 5;     // Error: i was not declared in this scope
        this->i = 5;  // compiles
    }
};

我的问题是:如何使用更新的编译器编译这个库?

库代码到处都使用了错误的语法 (i=5),所以我宁愿避免手动将整个库更改为“this->i=5”。提供的链接建议“使用”语句,但虽然这会减少我的工作,但我的首选方法不涉及代码更改,但会强制编译器对这些变量采用“假定”的旧行为。我找不到适合这种情况的编译器开关,-std=c++98-fpermissive 等都不起作用。

引自 C++-FAQ:

Perhaps surprisingly, the following code is not valid C++, even though some compilers accept it:

我也尝试使用 CLang++,结果相同。哪些编译器会接受此代码而无需更改?

编辑:按照 Brian 的建议,添加了关于 -fpermissive 的信息

最佳答案

不幸的是,正如@Mat 在评论中所说,这里唯一可行的选择是更正代码(并且您已经证明您已经知道如何去做)。

这是两阶段名称查找的结果,因此要让编译器接受它,您需要一个不实现两阶段名称查找的编译器。使用 Microsoft 的编译器,您可以使用 -Zc:twoPhase- 标志来获得当前编译器的旧行为(即,让编译器按原样接受您的代码)。

如果没记错的话,从 g++ 4.7 开始,g++ 的两阶段名称查找相当正确。我非常有信心所有 g++ 3.x 系列仍会接受您的代码,早期的 g++ 4.x 可能也会接受,但我很确定 g++ 4.7 及更高版本会拒绝它。

至于 Clang——如果没记错的话,它从一开始就有两个阶段的名称查找。早期版本无疑有一些错误,所以其中一个几乎不可能允许这样做,但我有点怀疑——这几乎是两阶段名称查找破坏现有代码的经典演示,所以任何试图这样做的编译器实现两阶段名称查找几乎肯定有与此类似的测试用例。

关于c++ - 如何在不更改所有代码以使用 this-> 的情况下避免旧模板重库中的 'not declared' 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53251331/

相关文章:

c++ - 如何从仅包含字母的 vector 字符串中删除?我的代码没有删除我需要删除的每个字符串

c++ - 请求分号的混淆错误(错误 C2143)

c++ - 可变参数模板的罕见错误?

c++ - 条件显式模板实例化

Cygwin、gcc 和 C_INCLUDE_PATH

c++ - exit(3) 在 Linux C++ 中挂起

自定义警告为 printf 的 "too many arguments for format"

c++ - 当没有抛出异常时,C++ 异常以什么方式减慢代码速度?

c++ - 构建 libiconv 库

c++ - 推导的模板 arg 和自动 arg 之间有什么区别吗?