c++ - vector/算法与 iostream 之间的不兼容性

标签 c++ c++builder-6

旧版本的 Borland C++ 编译器在使用 std::remove 的正确重载时似乎有问题 <iostream>已包含在内。

要重现此错误,您需要旧版本的 Borland C++ Builder(例如 C++ Builder 6)和这个非常小的代码片段:

#include <vector>
#include <algorithm>

void __fastcall TFormMain::Button1Click(TObject *Sender)
{
    std::vector< int > Selection;
    std::remove( Selection.begin(), Selection.end(), 10 );
}

(我知道:这段代码什么都不做,但至少它编译...)

一切正常,直到您在代码中的某处包含 iostream:

#include <vector>
#include <iostream>
#include <algorithm>

void __fastcall TFormMain::Button1Click(TObject *Sender)
{
    std::vector< int > Selection;
    std::remove( Selection.begin(), Selection.end(), 10 );
}

这会导致一些编译错误:

[C++ Fehler] UnitFormMain.cpp(22): E2034 Konvertierung von 'int *' nach 'const char *' nicht möglich
[C++ Fehler] UnitFormMain.cpp(22): E2342 Keine Übereinstimmung des Typs beim Parameter '__path' ('const char *' erwartet, 'int *' erhalten)
[C++ Fehler] UnitFormMain.cpp(22): E2227 Zu viele Parameter im Aufruf von std::remove(const char *)

英语:

[C++ Error] UnitFormMain.cpp(22): E2034 Cannot convert 'int *' to 'const char *'
[C++ Error] UnitFormMain.cpp(22): E2342 Type mismatch in parameter '__path' (wanted 'const char *', got 'int *')
[C++ Error] UnitFormMain.cpp(22): E2227 Extra parameter in call to std::remove(const char *)

我的问题是:

有没有优雅/正确的方法来解决这个问题而不将代码分离到不同的文件中?

最佳答案

BCB6 有两个 STL 库 - STLPort 和 RogueWave。 STLPort 是默认设置,提供 RogueWave 是为了向后兼容以前的 BCB 版本。

您的代码正在尝试调用 STL std::remove()来自 <algorithm> 的功能STLPort 的 header (实际上在 <stl/_algo.h> 中定义):

template <class _ForwardIter, class _Tp>
_STLP_INLINE_LOOP _ForwardIter 
remove(_ForwardIter __first, _ForwardIter __last, const _Tp& __value)

但是,C 运行时库有一个单参数 remove() 自己的功能,在<stdio.h> header :

int       _RTLENTRY _EXPFUNC remove(const char * __path);

此 C 函数被带入 std C++ 中的命名空间 <cstdio> header ,STLPort 的 <algorithm> header 包括。甚至还有关于 remove() 的评论在 <algorithm> 的位置包括 <cstdio>之前 <stl/_algo.h> :

# if ! defined (_STLP_USE_NAMESPACES)
// remove() conflicts, <cstdio> should always go first
#  include <cstdio>
# endif

# ifndef _STLP_INTERNAL_ALGO_H
#  include <stl/_algo.h>
# endif

甚至_algo.h有类似的评论:

# ifdef __SUNPRO_CC
// remove() conflict
#  include <cstdio>
# endif

因此,STLPort 始终包含 <cstdio>在定义自己的 remove() 之前算法,应该来处理命名冲突。

但是,话虽这么说,您看到的所有错误都是由于编译器认为您正在尝试调用 1 参数 std::remove()。 C 函数而不是 3 参数 std::remove() STL 函数。为什么编译器这么认为,我不知道。这可能是 BCB6 如何解决重载的编译器错误。

但是,该问题仅影响 STLPort,不影响 RogueWave,因为 RogeWave 的 <algorithm> header 不会导致 <cstdio>被包括在内(事实上,RogueWave 甚至没有像 STLPort 那样尝试解决 C 和 STL 之间与 remove() 的任何命名冲突)。

因此,一种解决方案是启用 RogueWave 而不是 STLPort,方法是定义 _USE_OLD_RW_STL在任何 STL header 之前:

#define _USE_OLD_RW_STL
// alternatively, add `_USE_OLD_RW_STL` to the Conditionals
// list in the Project Options...

#include <vector>
#include <iostream>
#include <algorithm>

...

std::vector< int > Selection;
std::remove( Selection.begin(), Selection.end(), 10 ); // WORKS

否则,如果你想使用STLPort,你可以使用Kamil Cuk在评论中提到的建议:

#include <vector>

#define remove _mask_remove
#include <iostream>
#undef remove

#include <algorithm>

...

std::vector< int > Selection;
std::remove( Selection.begin(), Selection.end(), 10 ); // WORKS

或者,使用 answer proposed by StoryTeller :

#include <vector>
#include <algorithm>

namespace resolve_std {
    using std::remove;
}

#include <iostream>

...

std::vector< int > Selection;
resolve_std::remove( Selection.begin(), Selection.end(), 10 ); // WORKS

我已经在 BCB6 中测试了所有这些解决方案,它们都适用于这种情况。

关于c++ - vector/算法与 iostream 之间的不兼容性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55683587/

相关文章:

c++复制初始化和直接初始化,奇怪的情况

c++ - 为什么 g++ 似乎混淆了数据类型?

c++ - 检查是否单击了任何其他按钮

c++ - 如何解决 [Linker Error] Unresolved external in Borland C++ builder 6

c++ - 将 DLL 代码从 Borland C++ Builder 6 移植到 Microsoft Visual C

c++ - 将非常大且旧的 C++Builder 代码移植/重新编码到 Qt 或 CLI/Mono

c++ - 为什么这个模板总是评估为 false_type?

c++ - 从单独的线程访问单独的文件,这是否有效?

c++ - SFML 文本未绘制在窗口上

c++ - MessageBox "Abnormal program termination"让我的应用程序保持运行