In my current pet project I try to use the STL as much as possible. There's no real reason except to learn how it works, doing it the old way would probably save me a lot of headaches and even more time. This is a simple function and I could have written it in about 10 other ways to make it work. The goal is to make it work STL style. However, my STL style obsession has it's limits, I'm not going to write a ten line functor of my own to supply to a three line STL function when I can have the whole thing done in one simple loop myself.
The function digits_only takes a string and removes everything that is not a digit according to the given locale. It took me a while to recognize the remove_if is not really "removing if". However, it takes a single argument to decide if a container element is to be removed, a so-called predicate, a function that takes a container element and returns a bool.
I tried various variants of what I thought should have worked but was greeted with a lot of cryptic error messages. Sorry for copying only generic english error messages, but I use a German version and those messages are probably even less helpful.
Code:
#include <string>
#include <iostream>
#include <cctype>
#include <algorithm>
#include <locale>
#include <functional>
using namespace std;
void digits_only( std::wstring& s, const locale& loc = locale("") )
{
wstring::iterator erasor = remove_if( s.begin(), s.end(), std::isdigit );
// works fine... except for not doing what I want, I need the digits to stay and remove only the non-digits
// plus, as of now it's not recognizing the supplied locale
// trying to add a logical not for removing anything that's not a digit:
//wstring::iterator erasor = remove_if( s.begin(), s.end(), logical_not( std::isdigit ) );
// error C2440: 'conversion' : cannot convert from 'type1' to 'type2'
//wstring::iterator erasor = remove_if( s.begin(), s.end(), logical_not( std::isdigit<wchar_t> ) );
// error C2440: 'conversion' : cannot convert from 'type1' to 'type2'
//wstring::iterator erasor = remove_if( s.begin(), s.end(), not1( std::isdigit<wchar_t> ) );
// error C2784: 'declaration' : could not deduce template argument for 'type' from 'type'
// gave up and tried to bind the locale as a second parameter first
//wstring::iterator erasor = remove_if( s.begin(), s.end(), bind2nd( std::isdigit, loc ) );
// error C2896 'function1 ' : cannot use function template 'function2' as argument.
//wstring::iterator erasor = remove_if( s.begin(), s.end(), bind2nd( std::isdigit<wchar_t>, loc ) );
// error C2784 'declaration' : could not deduce template argument for 'type' from 'type'
s.erase( erasor, s.end() );
}
int main()
{
wstring text = L"a1b2c3";
digits_only( text );
wcout << text << endl;
return 0;
}