我正在阅读O'Reilly的《 C++ Cookbook》一书,并尝试其中的一个示例,代码如下:

#include <string>
#include <iostream>
#include <cctype>
#include <cwctype>

using namespace std;

template<typename T, typename F>
void rtrimws(basic_string<T>& s, F f){
    if(s.empty())
        return;

    typename basic_string<T>::iterator p;
    for(p = s.end(); p != s.begin() && f(*--p););

    if(!f(*p))
        p++;

    s.erase(p, s.end());
}

void rtrimws(string& ws){
    rtrimws(ws, isspace);
}

void rtrimws(wstring& ws){
    rtrimws(ws, iswspace);
}

int main(){
    string s = "zing            ";
    wstring ws = L"zonh     ";

    rtrimws(s);
    rtrimws(ws);

    cout << s << "|\n";
    wcout << ws << "|\n";
}

当我尝试编译它时,出现以下错误
trim.cpp: In function ‘void rtrimws(std::string&)’:
trim.cpp:22: error: too many arguments to function ‘void rtrimws(std::string&)’
trim.cpp:23: error: at this point in file

而且我不明白怎么了。如果我不使用char版本(字符串),而仅使用wchar_t版本,则一切运行顺利。

顺便说一句,我在64位的ubuntu机器上使用g++ 4.4.3

最佳答案

isspace也是C++中的模板,它接受模板化字符,并且还接受语言环境,使用facet std::ctype<T>对给定字符进行分类(因此,它无法确定要采用哪个版本,因此忽略了模板) 。

尝试指定您的意思是C兼容版本:static_cast<int(*)(int)>(isspace)。编译器之间的差异可能是由于编译器之间对重载函数名的推论处理不一致所致-参见此clang PR。有关类似情况,请参见Faisal第一组测试用例中的第二种情况。

有人在IRC上指出,此代码将使用isspace调用char-但isspace接受int并要求指定的值在unsigned char值或EOF的范围内。现在,如果char在您的PC上签名并存储负的非EOF值,这将导致未定义的行为。

我建议像@Kirill在评论中所说的那样做,只使用模板化的std::isspace-然后您也可以摆脱函数对象参数。

关于c++ - 重载函数未编译,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3679801/

10-10 08:09