开发者

ctype and strings and containers

Is there any reason that the ctype facet functions (is,scan_is,scan_not only support plain char pointer, and not iterator based containers, like std::string or even a std::vector... then one could write:

const ctype<char>& myctype = use_facet<std::ctype<char> >(locale(""));
string foo_str = "hi there here is a number: 748574 and text again";
vector<char> foo(foo_str.begin(),foo_str.end());

//then one could write

vector<char>::iterator num_begin_it = myctype.scan_is( ctype<char>::digit, foo.begin(), foo.end() );
vector<char> foo_num_1( foo, num_begin_it, myctype.scan_not(ctype<char>::digit, num_begin_it, foo.end() );

//instead of:
const char* num_begin_pc = myctype.scan_is(ctype<char>::digit, &foo[0], &foo[foo.size()-1]+1); // &foo[foo.size()-1]+1) instead of foo.end() is not quite readable.
vector<char> foo_num_2(num_begin_pc, myctype.scan_not(ctype<char>::digit, num_begin_pc, &foo[foo.size()-1]+1));

//appendix:
//STL/Boost solution, even more verbose:

function<bool(char)> is_digit_func =
    bind(
        mem_fn(static_cast<bool (ctype<char>::*)(ctype<char>::mask,char) const>(&ctype<char>::is)),
        &myctype,
        ctype<char>::digit,
        _1
    );
vector<char>::iterator num_begin_0x = find_if(foo.begin(), foo.end(),is_digit_func);
vector<char> foo_开发者_如何学运维num_3(num_begin_0x,find_if(num_begin_0x, foo.end(),not1(is_digit_func)));

// all 3 foo_num_X will now contain "748574"

Would be cool if anyone has some insight why the standard committee made those design decisions ?

And is there a better (=less verbose) way to make use of the ctype functions with iterator-based containers ?

The STL/Boost solution would be kinda OK, if it wouldnt need that

Additionally i found that there is no copy_if algorithm in the standard library, but i already the reason for this.


The main reason is that the Standard Library wasn't developed as a single coherent whole, but incorporates several libraries that were popular at the time.

Iterators were a concept from the "Standard Template Library", which was the basis for the standard Containers, Iterators and Algorithms libraries. The Strings and Localization libraries came from other sources, which did not use iterators. Because iterators are so useful, it was deemed worth the effort of retrofitting them to these libraries, but not to completely change the libraries' interfaces to use iterators everywhere.

By the way, you might find &foo.back()+1 or &foo[0] + foo.size() to be more readable than &foo[foo.size()-1]+1. You also don't need to copy the string into a vector to use scan_is and scan_not; something like this should do the job:

const char* str_begin = foo_str.c_str();
const char* str_end   = str_begin + foo_str.length();
const char* num_begin = myctype.scan_is(ctype<char>::digit, str_begin, str_end);
const char* num_end   = myctype.scan_not(ctype<char>::digit, num_begin, str_end);
std::string number(num_begin, num_end); // or `vector` if you really want
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜