Перегрузка функций не компилируется - PullRequest
2 голосов
/ 09 сентября 2010

Я слежу за книгой C ++ Cookbook от O'Reilly и пробую один из примеров, вот код:

#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, все работает гладко.

Кстати, я использую g ++ 4.4.3 в машине с Ubuntu 64 бит

Ответы [ 3 ]

1 голос
/ 09 сентября 2010

isspace также является шаблоном в C ++, который принимает шаблонный символ, а также локаль, с которой он использует фасет std::ctype<T> для классификации данного символа (поэтому он не может решить, какую версию взять,и как таковой игнорирует шаблон).

Попробуйте указать, что вы имеете в виду версию совместимости C: static_cast<int(*)(int)>(isspace).Различия между компиляторами могут быть связаны с непоследовательной обработкой вывода из имени перегруженной функции среди компиляторов - см. Этот clang PR .См. Второй случай в первом наборе тестов Фейсала для аналогичного случая.


Кто-то указал на IRC, что этот код будет вызывать isspace, используя char - но isspace принимает int и требует, чтобы значение было в диапазоне unsigned charзначения или EOF.Теперь, если char подписано на вашем ПК и хранит отрицательное значение, отличное от EOF, это приведет к неопределенному поведению.

Я рекомендую сделать это так, как говорит @Kirill в комментарии, и просто использовать шаблон std::isspace - тогда вы также можете избавиться от аргумента объекта функции.

1 голос
/ 09 сентября 2010

Попробуйте rtrimws(ws, ::isspace);.

Также, как примечание, вы должны использовать обратный итератор.

0 голосов
/ 09 сентября 2010

Это потому, что isspace является функцией шаблона в c ++. Это не может вывести F. Если вы хотите использовать вариант C isspace, вы можете полностью указать его имя следующим образом:

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

Это еще один хороший пример, почему вы не должны использовать using namespace std.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...