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

  // Process a vector

  vector v;

  v.push_back(1);

  v.push_back(2);

  printSeq(v);

  // Process a list

  list lst;

  lst.push_back(3);

  lst.push_back(4);

  printSeq(lst);

} ///:~

Once again, without the typename keyword the compiler will interpret iterator as a static data member of Seq, which is a syntax error, since a type is required.

<p>Typedef-ing a typename</p>

It’s important not to assume that the typename keyword creates a new type name. It doesn’t. Its purpose is to inform the compiler that the qualified identifier is to be interpreted as a type. A line that reads:.

typename Seq::iterator It;

causes a variable named It to be declared of type Seq::iterator. If you mean to create a new type name, you should use typedef, as usual, as in:.

typedef typename Seq::iterator It;

<p>Using typename instead of class</p>

Another role of the typename keyword is to provide you the option of using typename instead of class in the template argument list of a template definition. To some, this produces clearer code (your mileage may vary):.

//: C05:UsingTypename.cpp

// Using 'typename' in the template argument list

template class X { };

int main() {

  X x;

} ///:~

You probably won’t see a great deal of code that uses typename in this fashion, since the keyword was added to the language a relatively long time after templates were introduced.

<p>Using the template keyword as a hint</p>

Just as the typename keyword helps the compiler in situations in which a type identifier is not expected, there is also a potential difficulty with tokens that are not identifiers, such as the < and > characters; sometimes they represent the less-than or greater-than symbols, and sometimes they delimit template parameter lists. As an example, we’ll once more use the bitset class:.

//: C05:DotTemplate.cpp

// Illustrate the .template construct

#include

#include

#include

#include

using namespace std;

template

basic_string bitsetToString(const bitset& bs) {

  return bs. template to_string,

                                allocator >();

}

int main() {

  bitset<10> bs;

  bs.set(1);

  bs.set(5);

  cout << bs << endl; // 0000100010

  string s = bitsetToString(bs);

  cout << s << endl;  // 0000100010

} ///:~

The bitset class supports conversion to string object via its to_string member function. To support multiple string classes, to_string is itself a template, following the pattern established by the basic_string template discussed in Chapter 3. The declaration of to_string inside of bitset looks like this:.

template

basic_string to_string() const;

Our bitsetToString( ) function template above allows you to request different types of string representations of a bitset. To get a wide string, for instance, you change the call to the following:

  wstring s = bitsetToString(bs);

Note that basic_string uses default template arguments, so we don’t have to repeat the char_traits and allocator arguments in the return value. Unfortunately, bitset::to_string does not use default arguments. Using bitsetToString( bs) is more convenient than typing a fully-qualified call to bs.template to_string >( ) every time.

The return statement in bitsetToString( ) contains the template keyword in an odd place—right after the dot operator applied to the bitset object bs. This is because when the template is parsed, the < character after the to_string token would be interpreted as a less-than operation instead of the beginning or a template argument list. We explain exactly why this confusion exists in the section "Name lookup issues" later in this chapter. The template keyword used in this context tells the compiler that what follows is the name of a template, causing the < character to be interpreted correctly. The same reasoning applies to the -> and :: operators when applied to templates. As with the typename keyword, this template disambiguation technique can only be used within a template.[50] 

<p>Member Templates</p>

The bitset::to_string( ) function template is an example of a member template: a template declared within another class or class template. This allows many combinations of independent template arguments to be combined. A useful example is found in the complex class template in the standard C+ library. The complex template has a type parameter meant to represent an underlying floating-point type to hold the real and imaginary parts of a complex number. The following code snippet from the standard library shows a member-template constructor in the complex class template:.

template

class complex {

public:

  template complex(const complex&);

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

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

3ds Max 2008
3ds Max 2008

Одни уверены, что нет лучшего способа обучения 3ds Мах, чем прочитать хорошую книгу. Другие склоняются к тому, что эффективнее учиться у преподавателя, который показывает, что и как нужно делать. Данное издание объединяет оба подхода. Его цель – сделать освоение 3ds Мах 2008 максимально быстрым и результативным. Часто после изучения книги у читателя возникают вопросы, почему не получился тот или иной пример. Видеокурс – это гарантия, что такие вопросы не возникнут: ведь автор не только рассказывает, но и показывает, как нужно работать в 3ds Мах.В отличие от большинства интерактивных курсов, где работа в 3ds Мах иллюстрируется на кубиках-шариках, данный видеокурс полностью практический. Все приемы работы с инструментами 3ds Мах 2008 показаны на конкретных примерах, благодаря чему после просмотра курса читатель сможет самостоятельно выполнять даже сложные проекты.

Владимир Антонович Верстак , Владимир Верстак

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