开发者

Overloading functions not compiling

I am following the book C++ Cookbook from O'Reilly and I try one of the examples, here is the code:

#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, is开发者_开发百科wspace);
}

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

    rtrimws(s);
    rtrimws(ws);

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

When I try to compile it, I get the following error

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

and I don't understand what's wrong. If I don't use the char version (string) but the wchar_t version only, everything runs smooth.

By the way, I am using g++ 4.4.3 in an ubuntu machine 64 bits


isspace is also a template in C++ which accepts a templated character and also a locale with which it uses the facet std::ctype<T> to classify the given character (so it can't make up its mind what version to take, and as such ignores the template).

Try specifying that you mean the C compatibility version: static_cast<int(*)(int)>(isspace). The differences between the compilers could come from the inconsistent handling of deduction from an overloaded function name among the compilers - see this clang PR. See the second case in Faisal's first set of testcases for an analogous case.


Someone pointed out on IRC that this code would call isspace using a char - but isspace takes int and requires the value given to be in the range of unsigned char values or EOF. Now in case that char is signed on your PC and stores a negative non-EOF value, this will yield to undefined behavior.

I recommend to do it like @Kirill says in a comment and just use the templated std::isspace - then you can get rid of the function object argument too.


Try rtrimws(ws, ::isspace);.

Also, just as a note, you should be using the reverse iterator.


That's because isspace is a template function in c++. It cannot deduce F. If you want to use C variant of isspace you could fully qualify its name as follows:

void rtrimws(string& ws){
    rtrimws(ws, ::isspace); // this will use isspace from global namespace
                            // C++ version belongs to the namespace `std`
}

This is one more good sample why you shouldn't use using namespace std.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜