Читаем Thinking In C++. Volume 2: Practical Programming полностью

An obscure issue arises when trying to pass the functions tolower or toupper, declared in , as parameters. It is possible to use these in conjunction with the transform algorithm (which is covered in detail in the next chapter), for example, to convert a string to lower or upper case. Care must be taken, however, because there are multiple declarations for these functions. A naïve approach would is something like this:.

// The variable s is a std::string

transform(s.begin(), s.end(), s.begin(), tolower);

The transform algorithm applies its fourth parameter (tolower in this case) to each character in the string s and places the result in s itself, thus overwriting each character in s with its lower-case equivalent. As it is written, this statement may or may not work! It fails in the following context:.

#include

#include

#include

#include

using namespace std;

int main() {

  string s("LOWER");

  transform(s.begin(),s.end(),s.begin(),tolower);

  cout << s << endl;

}

Even if your compiler let’s you get away with this, it is illegal. The reason is that the header also makes available a two-argument version of tolower and toupper:

template charT toupper(charT c,

                      const locale& loc);

template charT tolower(charT c,

                      const locale& loc);

These function templates take a second argument of type locale. The compiler has no way of knowing whether it should use the one-argument version of tolower defined in or the one mentioned above. You can solve this problem (almost!) with a cast in the call to transform, as follows:.

  transform(s.begin(),s.end(),s.begin()

            static_cast(tolower));

(Recall that tolower and toupper traffic in int instead of char.) The cast above makes clear that the single-argument version of tolower is desired. Once again, this works with some compilers, but it is not required to. The reason, albeit obscure, is that a library implementation is allowed to give "C linkage" (meaning that the function name does not contain all the auxiliary information[54] that normal C++ functions do) to functions inherited from the C language. If this is the case, the cast fails, because transform is a C++ function template and expects its fourth argument to have C++ linkage—and a cast is not allowed to change the linkage. What a predicament!.

The solution is to place calls to tolower in an unambiguous context. For example, you could write a function, let’s call it strTolower( ), and place it in its own file without including , like this:.

//: C05:StrTolower.cpp {O}

#include

#include

#include

using namespace std;

string strTolower(string s) {

  transform(s.begin(), s.end(), s.begin(), tolower);

  return s;

} ///:~

The header is not involved here, and the compilers we use do not introduce the two-argument version of tolower in this context,[55] so there’s no problem. You can then use this function normally:.

//: C05:Tolower.cpp

//{L} StrTolower

#include

#include

#include

#include

using namespace std;

string strTolower(string);

int main() {

  string s("LOWER");

  cout << strTolower(s) << endl;

} ///:~

Another solution is to write a wrapper function template that calls the correct version of tolower explicitly:

//: C05:ToLower2.cpp

#include

#include

#include

#include

using namespace std;

template

charT strTolower(charT c) {

  return tolower(c);  // one-arg version called

}

int main() {

  string s("LOWER");

  transform(s.begin(),s.end(),s.begin(),&strTolower);

  cout << s << endl;

} ///:~

This version has the advantage that it can process both wide and narrow strings since the underlying character type is a template parameter. The C++ standards committee is working on modifying the language so that the first example (without the cast) will work, and some day these workarounds can be ignored.[56] 

<p>Applying a function to an STL sequence</p>

Suppose you want to take an STL sequence container (which you’ll learn more about in subsequent chapters; for now we can just use the familiar vector) and apply a function to all the objects it contains. Because a vector can contain any type of object, you need a function that works with any type of vector:.

//: C05:ApplySequence.h

// Apply a function to an STL sequence container

// 0 arguments, any type of return value:

template

void apply(Seq& sq, R (T::*f)()) {

  typename Seq::iterator it = sq.begin();

  while(it != sq.end()) {

    ((*it)->*f)();

    it++;

  }

}

// 1 argument, any type of return value:

template

void apply(Seq& sq, R(T::*f)(A), A a) {

  typename Seq::iterator it = sq.begin();

  while(it != sq.end()) {

    ((*it)->*f)(a);

    it++;

  }

}

// 2 arguments, any type of return value:

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных