Scott Meyers - Effective Modern C++

Здесь есть возможность читать онлайн «Scott Meyers - Effective Modern C++» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Город: Sebastopol, Год выпуска: 2014, ISBN: 2014, Издательство: O’Reilly, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Effective Modern C++: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Effective Modern C++»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Coming to grips with C++11 and C++14 is more than a matter of familiarizing yourself with the features they introduce (e.g., auto type declarations, move semantics, lambda expressions, and concurrency support). The challenge is learning to use those features
— so that your software is correct, efficient, maintainable, and portable. That's where this practical book comes in. It describes how to write truly great software using C++11 and C++14 — i.e., using
C++.
Topics include:
■ The pros and cons of braced initialization,
specifications, perfect forwarding, and smart pointer make functions
■ The relationships among
,
, rvalue references, and universal references
■ Techniques for writing clear, correct,
lambda expressions
■ How
differs from
, how each should be used, and how they relate to C++'s concurrency API
■ How best practices in “old” C++ programming (i.e., C++98) require revision for software development in modern C++
Effective Modern C++ For more than 20 years,
'
books (
,
, and
) have set the bar for C++ programming guidance. His clear, engaging explanations of complex technical material have earned him a worldwide following, keeping him in demand as a trainer, consultant, and conference presenter. He has a Ph.D. in Computer Science from Brown University.
“After I learned the C++ basics, I then learned how to use C++ in production code from Meyers' series of Effective C++ books. Effective Modern C++ is the most important how-to book for advice on key guidelines, styles, and idioms to use modern C++ effectively and well. Don't own it yet? Buy this one. Now.”
Herb Sutter
Chair of ISO C++ Standards Committee and C++ Software Architect at Microsoft

Effective Modern C++ — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Effective Modern C++», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

But perfect forwarding has drawbacks. One is that some kinds of arguments can't be perfect-forwarded, even though they can be passed to functions taking specific types. Item 30explores these perfect forwarding failure cases.

A second issue is the comprehensibility of error messages when clients pass invalid arguments. Suppose, for example, a client creating a Personobject passes a string literal made up of char16_ts (a type introduced in C++11 to represent 16-bit characters) instead of chars (which is what a std::stringconsists of):

Person p( u"Konrad Zuse"); // "Konrad Zuse" consists of

// characters of type const char16_t

With the first three approaches examined in this Item, compilers will see that the available constructors take either intor std::string, and they'll produce a more or less straightforward error message explaining that there's no conversion from const char16_t[12]to intor std::string.

With an approach based on perfect forwarding, however, the array of const char16_ts gets bound to the constructor's parameter without complaint. From there it's forwarded to the constructor of Person's std::stringdata member, and it's only at that point that the mismatch between what the caller passed in (a const char16_tarray) and what's required (any type acceptable to the std::stringconstructor) is discovered. The resulting error message is likely to be, er, impressive. With one of the compilers I use, it's more than 160 lines long.

In this example, the universal reference is forwarded only once (from the Personconstructor to the std::stringconstructor), but the more complex the system, the more likely that a universal reference is forwarded through several layers of function calls before finally arriving at a site that determines whether the argument type(s) are acceptable. The more times the universal reference is forwarded, the more baffling the error message may be when something goes wrong. Many developers find that this issue alone is grounds to reserve universal reference parameters for interfaces where performance is a foremost concern.

In the case of Person, we know that the forwarding function's universal reference parameter is supposed to be an initializer for a std::string, so we can use a static_assertto verify that it can play that role. The std::is_constructibletype trait performs a compile-time test to determine whether an object of one type can be constructed from an object (or set of objects) of a different type (or set of types), so the assertion is easy to write:

class Person {

public:

template< // as before

typename T,

typename = std::enable_if_t<

!std::is_base_of>::value

&&

!std::is_integral>::value

>

>

explicit Person(T&& n)

: name(std::forward(n)) {

// assert that a std::string can be created from a T object

static_assert(

std::is_constructible::value,

"Parameter n can't be used to construct a std::string"

);

… // the usual ctor work goes here

}

… // remainder of Person class (as before)

};

This causes the specified error message to be produced if client code tries to create a Personfrom a type that can't be used to construct a std::string. Unfortunately, in this example the static_assertis in the body of the constructor, but the forwarding code, being part of the member initialization list, precedes it. With the compilers I use, the result is that the nice, readable message arising from the static_assertappears only after the usual error messages (up to 160-plus lines of them) have been emitted.

Things to Remember

• Alternatives to the combination of universal references and overloading include the use of distinct function names, passing parameters by lvalue reference-to- const, passing parameters by value, and using tag dispatch.

• Constraining templates via std::enable_ifpermits the use of universal references and overloading together, but it controls the conditions under which compilers may use the universal reference overloads.

• Universal reference parameters often have efficiency advantages, but they typically have usability disadvantages.

Item 28: Understand reference collapsing.

Item 23remarks that when an argument is passed to a template function, the type deduced for the template parameter encodes whether the argument is an lvalue or an rvalue. The Item fails to mention that this happens only when the argument is used to initialize a parameter that's a universal reference, but there's a good reason for the omission: universal references aren't introduced until Item 24. Together, these observations about universal references and lvalue/rvalue encoding mean that for this template,

template

void func(T&& param);

the deduced template parameter Twill encode whether the argument passed to paramwas an lvalue or an rvalue.

The encoding mechanism is simple. When an lvalue is passed as an argument, Tis deduced to be an lvalue reference. When an rvalue is passed, Tis deduced to be a non-reference. (Note the asymmetry: lvalues are encoded as lvalue references, but rvalues are encoded as non-references .) Hence:

Widget widgetFactory(); // function returning rvalue

Widget w; // a variable (an lvalue)

func(w); // call func with lvalue; T deduced

// to be Widget&

func(widgetFactory()); // call func with rvalue; T deduced

// to be Widget

In both calls to func, a Widgetis passed, yet because one Widgetis an lvalue and one is an rvalue, different types are deduced for the template parameter T. This, as we shall soon see, is what determines whether universal references become rvalue references or lvalue references, and it's also the underlying mechanism through which std::forwarddoes its work.

Before we can look more closely at std::forwardand universal references, we must note that references to references are illegal in C++. Should you try to declare one, your compilers will reprimand you:

int x;

auto & &rx = x; // error! can't declare reference to reference

But consider what happens when an lvalue is passed to a function template taking a universal reference:

template

void func(T&& param); // as before

func(w); // invoke func with lvalue;

// T deduced as Widget&

If we take the type deduced for T(i.e., Widget&) and use it to instantiate the template, we get this:

void func( Widget& &&param);

A reference to a reference! And yet compilers issue no protest. We know from Item 24that because the universal reference paramis being initialized with an lvalue, param's type is supposed to be an lvalue reference, but how does the compiler get from the result of taking the deduced type for T and substituting it into the template to the following, which is the ultimate function signature?

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Effective Modern C++»

Представляем Вашему вниманию похожие книги на «Effective Modern C++» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Effective Modern C++»

Обсуждение, отзывы о книге «Effective Modern C++» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x