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++», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

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

Интервал:

Закладка:

Сделать

Success, right? We're done!

Um, no. Belay that celebration. There's still one loose end from Item 26that continues to flap about. We need to tie it down.

Suppose a class derived from Personimplements the copy and move operations in the conventional manner:

class SpecialPerson: public Person {

public:

SpecialPerson(const SpecialPerson& rhs) // copy ctor; calls

: Person(rhs) // base class

{ … } // forwarding ctor!

SpecialPerson(SpecialPerson&& rhs) // move ctor; calls

: Person(std::move(rhs)) // base class

{ … } // forwarding ctor!

};

This is the same code I showed in Item 26(on page 206), including the comments, which, alas, remain accurate. When we copy or move a SpecialPersonobject, we expect to copy or move its base class parts using the base class's copy and move constructors, but in these functions, we're passing SpecialPersonobjects to the base class's constructors, and because SpecialPersonisn't the same as Person(not even after application of std::decay), the universal reference constructor in the base class is enabled, and it happily instantiates to perform an exact match for a SpecialPersonargument. This exact match is better than the derived-to-base conversions that would be necessary to bind the SpecialPersonobjects to the Personparameters in Person's copy and move constructors, so with the code we have now, copying and moving SpecialPersonobjects would use the Personperfect-forwarding constructor to copy or move their base class parts! It's déjà Item 26all over again.

The derived class is just following the normal rules for implementing derived class copy and move constructors, so the fix for this problem is in the base class and, in particular, in the condition that controls whether Person's universal reference constructor is enabled. We now realize that we don't want to enable the templatized constructor for any argument type other than Person, we want to enable it for any argument type other than Person or a type derived from Person . Pesky inheritance!

You should not be surprised to hear that among the standard type traits is one that determines whether one type is derived from another. It's called std::is_base_of. std::is_base_of::valueis true if T2is derived from T1. Types are considered to be derived from themselves, so std::is_base_of::valueis true. This is handy, because we want to revise our condition controlling Person's perfect- forwarding constructor such that the constructor is enabled only if the type T, after stripping it of references and cv-qualifiers, is neither Personnor a class derived from Person. Using std::is_base_ofinstead of std::is_samegives us what we need:

class Person {

public:

template<

typename T,

typename = typename std::enable_if<

!std:: is_base_of

typename std::decay::type

>::value

>::type

>

explicit Person(T&& n);

};

Now we're finally done. Provided we're writing the code in C++11, that is. If we're using C++14, this code will still work, but we can employ alias templates for std::enable_ifand std::decayto get rid of the “ typename” and “ ::type” cruft, thus yielding this somewhat more palatable code:

class Person { // C++14

public:

template<

typename T,

typename = std::enable_if _t< // less code here

!std::is_base_of

std::decay _t // and here

>::value

> // and here

>

explicit Person(T&& n);

};

Okay, I admit it: I lied. We're still not done. But we're close. Tantalizingly close. Honest.

We've seen how to use std::enable_ifto selectively disable Person's universal reference constructor for argument types we want to have handled by the class's copy and move constructors, but we haven't yet seen how to apply it to distinguish integral and non-integral arguments. That was, after all, our original goal; the constructor ambiguity problem was just something we got dragged into along the way.

All we need to do — and I really do mean that this is everything — is (1) add a Personconstructor overload to handle integral arguments and (2) further constrain the templatized constructor so that it's disabled for such arguments. Pour these ingredients into the pot with everything else we've discussed, simmer over a low flame, and savor the aroma of success:

class Person {

public:

template<

typename T,

typename = std::enable_if_t<

!std::is_base_of>::value

&&

!std::is_integral>::value

>

>

explicit Person(T&& n) // ctor for std::strings and

: name(std::forward(n)) // args convertible to

{ … } // std::strings

explicit Person(int idx) // ctor for integral args

: name(nameFromIdx(idx))

{ … }

… // copy and move ctors, etc.

private:

std::string name;

};

Voilà! A thing of beauty! Well, okay, the beauty is perhaps most pronounced for those with something of a template metaprogramming fetish, but the fact remains that this approach not only gets the job done, it does it with unique aplomb. Because it uses perfect forwarding, it offers maximal efficiency, and because it controls the combination of universal references and overloading rather than forbidding it, this technique can be applied in circumstances (such as constructors) where overloading is unavoidable.

Trade-offs

The first three techniques considered in this Item — abandoning overloading, passing by const T&, and passing by value — specify a type for each parameter in the function(s) to be called. The last two techniques — tag dispatch and constraining template eligibility — use perfect forwarding, hence don't specify types for the parameters. This fundamental decision — to specify a type or not — has consequences.

As a rule, perfect forwarding is more efficient, because it avoids the creation of temporary objects solely for the purpose of conforming to the type of a parameter declaration. In the case of the Personconstructor, perfect forwarding permits a string literal such as "Nancy"to be forwarded to the constructor for the std::stringinside Person, whereas techniques not using perfect forwarding must create a temporary std::stringobject from the string literal to satisfy the parameter specification for the Personconstructor.

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

Интервал:

Закладка:

Сделать

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

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


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

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

x