2010-07-19 4 views
2

Есть ли причина, по которой функции фасета ctype (is, scan_is, scan_not поддерживают только указатель на простой указатель, а не контейнеры на основе итератора, такие как std :: string или даже std :: vector ... тогда можно было бы написать:ctype и строки и контейнеры

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" 

Было бы здорово, если бы кто-нибудь имеет некоторое представление о том, почему стандартный комитет сделал эти проектные решения

И есть лучше (= менее многословным) способ использовать из? ctype-функции с контейнерами на основе итератора?

Решение STL/подталкивания будет своего рода хорошо, если это Wouldnt нужно что

Кроме того я обнаружил, что не существует алгоритма copy_if в стандартной библиотеке, но я уже reason for this.

+1

'std :: basic_string' имеет конструктор, который принимает два' InputIterator's. – Philipp

+0

@Phillip: Вы правы, удалили эту часть. – smerlin

ответ

2

Основная причина в том, что стандартная библиотека не была разработана как единое целое, но включает в себя несколько библиотек, которые были популярны в то время.

Итераторы были концепцией из «стандартной библиотеки шаблонов», которая была основой для стандартных библиотек контейнеров, итераторов и алгоритмов. Библиотеки строк и локализации поступали из других источников, которые не использовали итераторы. Поскольку итераторы настолько полезны, было сочтено целесообразным доработать их в этих библиотеках, но не полностью изменить интерфейсы библиотек для использования итераторов повсюду.

Кстати, вы можете найти &foo.back()+1 или &foo[0] + foo.size(), чтобы быть более читаемыми, чем &foo[foo.size()-1]+1. Вам также не нужно копировать строку в вектор для использования scan_is и scan_not; что-то вроде этого должно делать:

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

У меня есть только промежуточная std :: string, потому что вы не можете инициализировать вектор красиво строковым литералом. И мне нужен пример с вектором. – smerlin

+0

После того, как они приняли STL, они добавили итераторы в 'std :: string', но не в' std :: ctype'. Это кажется мне очень непоследовательным, тем более, что им не нужно было бы изменять представление клиента о интерфейсе на принципе 'template scan_is (mask m, InputIt low, InputIt low) const' не будет отличаться при вызове с помощью 'const char *', а затем 'const char *' - только интерфейс. IMO полная библиотека языка выглядит как C-with-Classes, особенно ctype и codecvt. – smerlin