首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >向量/算法与iostream不兼容

向量/算法与iostream不兼容
EN

Stack Overflow用户
提问于 2019-04-15 14:28:40
回答 2查看 198关注 0票数 1

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

要重现此错误,您需要一个老版本的Borland C++生成器(例如,C++生成器6)和以下非常小的代码片段:

代码语言:javascript
复制
#include <vector>
#include <algorithm>

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

(我知道:这段代码什么也不做,但至少它可以编译……)

一切正常,直到你在代码中的某个地方包含了iostream:

代码语言:javascript
复制
#include <vector>
#include <iostream>
#include <algorithm>

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

这将导致一些编译器错误:

代码语言:javascript
复制
[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 *)

在英语中:

代码语言:javascript
复制
[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 *)

我的问题是:

有没有什么优雅的/正确的方法来修复这个问题,而不是将代码分成不同的文件?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-04-16 09:05:15

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

您的代码试图从STLPort的<algorithm>头调用STL std::remove()函数(它实际上是在<stl/_algo.h>中定义的):

代码语言:javascript
复制
template <class _ForwardIter, class _Tp>
_STLP_INLINE_LOOP _ForwardIter 
remove(_ForwardIter __first, _ForwardIter __last, const _Tp& __value)

但是,C运行时库在<stdio.h>头文件中有自己的单参数remove()函数:

代码语言:javascript
复制
int       _RTLENTRY _EXPFUNC remove(const char * __path);

此C函数由<cstdio>头引入C++中的std名称空间,STLPort的<algorithm>头包括该头。甚至有一条关于remove()的评论,<algorithm><stl/_algo.h>之前包含了<cstdio>

代码语言:javascript
复制
# 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也有类似的评论:

代码语言:javascript
复制
# ifdef __SUNPRO_CC
// remove() conflict
#  include <cstdio>
# endif

因此,STLPort在定义自己的remove()算法之前总是包含<cstdio>,据说是为了处理命名冲突。

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

然而,这个问题只影响STLPort,而不影响RogueWave,因为RogeWave的<algorithm>头不会导致包含<cstdio> (事实上,RogueWave甚至不像STLPort那样尝试解决C和remove()之间的任何命名冲突)。

因此,一种解决方案是允许使用RogueWave而不是STLPort,方法是在任何STL头之前定义_USE_OLD_RW_STL

代码语言:javascript
复制
#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在评论中提到的建议:

代码语言:javascript
复制
#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

代码语言:javascript
复制
#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中测试了所有这些解决方案,它们都在这个场景中工作。

票数 4
EN

Stack Overflow用户

发布于 2019-04-15 15:33:45

有一些东西你可以尝试,但对此持保留态度,因为我没有可用的C++构建器来测试它。

using声明可以将名称从一个命名空间引入到另一个命名空间中,这可以在限定查找中使用。但是,只有在using声明时可见的重载才会被引入。因此,如果我们只获取我们想要的重载,并在新的名称空间上进行限定名称查找,就不应该有歧义。下面是代码:

代码语言:javascript
复制
#include <vector>
#include <algorithm>

namespace resolve_std {
    using std::remove;
}

#include <iostream>

void __fastcall TFormMain::Button1Click(TObject *Sender)
{
    std::vector< int > Selection;
    // Should only use the overloads introduced prior to including <iostream>
    resolve_std::remove( Selection.begin(), Selection.end(), 10 );
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55683587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档