Free Essay

The God of War

In:

Submitted By jahan007
Words 8814
Pages 36
Effective Modern C++

Topics include:
■■

The pros and cons of braced initialization, noexcept specifications, perfect forwarding, and smart pointer make functions ■■

The relationships among std::move, std::forward, rvalue references, and universal references

■■

Techniques for writing clear, correct, effective lambda expressions ■■

How std::atomic differs from volatile, 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++

After the C++
“ I learnedlearned basics, I then 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++

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 effectively—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 modern C++.

Effective Modern C++ follows the proven guideline-based, example-driven format of Scott Meyers' earlier books, but covers entirely new material. It's essential reading for every modern C++ software developer.

For more than 20 years, Scott Meyers' Effective C++ books (Effective C++, More
Effective C++, and Effective STL) 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.

US $49.99

Twitter: @oreillymedia facebook.com/oreilly Meyers

PROGR AMMING/C++

Effective
Modern C++
42 SPECIFIC WAYS TO IMPROVE YOUR USE OF C++11 AND C++14

CAN $52.99

ISBN: 978-1-491-90399-5

Scott Meyers

Effective Modern C++

Topics include:
■■

The pros and cons of braced initialization, noexcept specifications, perfect forwarding, and smart pointer make functions ■■

The relationships among std::move, std::forward, rvalue references, and universal references

■■

Techniques for writing clear, correct, effective lambda expressions ■■

How std::atomic differs from volatile, 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++

After the C++
“ I learnedlearned basics, I then 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++

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 effectively—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 modern C++.

Effective Modern C++ follows the proven guideline-based, example-driven format of Scott Meyers' earlier books, but covers entirely new material. It's essential reading for every modern C++ software developer.

For more than 20 years, Scott Meyers' Effective C++ books (Effective C++, More
Effective C++, and Effective STL) 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.

US $49.99

Twitter: @oreillymedia facebook.com/oreilly Meyers

PROGR AMMING/C++

Effective
Modern C++
42 SPECIFIC WAYS TO IMPROVE YOUR USE OF C++11 AND C++14

CAN $52.99

ISBN: 978-1-491-90399-5

Scott Meyers

O’Reilly Ebooks—Your bookshelf on your devices!

When you buy an ebook through oreilly.com you get lifetime access to the book, and whenever possible we provide it to you in five, DRM-free file formats—PDF, .epub,
Kindle-compatible .mobi, Android .apk, and DAISY—that you can use on the devices of your choice. Our ebook files are fully searchable, and you can cut-and-paste and print them. We also alert you when we’ve updated the files with corrections and additions.

Learn more at ebooks.oreilly.com
You can also purchase O’Reilly ebooks through the iBookstore, the Android Marketplace, and Amazon.com.

Spreading the knowledge of innovators

oreilly.com

Effective Modern C++ by Scott Meyers
Copyright © 2015 Scott Meyers. All rights reserved.
Printed in the Canada.
Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472.
O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://safaribooksonline.com). For more information, contact our corporate/ institutional sales department: 800-998-9938 or corporate@oreilly.com.

Editor: Rachel Roumeliotis
Production Editor: Melanie Yarbrough
Copyeditor: Jasmine Kwityn

November 2014:

Proofreader: Charles Roumeliotis
Indexer: Scott Meyers
Interior Designer: David Futato
Cover Designer: Ellie Volkhausen
Illustrator: Rebecca Demarest

First Edition

Revision History for the First Edition
2014-11-07:

First Release

See http://oreilly.com/catalog/errata.csp?isbn=9781491903995 for release details.
The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. Effective Modern C++, the cover image of a Rose-crowned Fruit Dove, and related trade dress are trademarks of O’Reilly Media, Inc.
While the publisher and the author have used good faith efforts to ensure that the information and instructions contained in this work are accurate, the publisher and the author disclaim all responsibility for errors or omissions, including without limitation responsibility for damages resulting from the use of or reliance on this work. Use of the information and instructions contained in this work is at your own risk. If any code samples or other technology this work contains or describes is subject to open source licenses or the intellectual property rights of others, it is your responsibility to ensure that your use thereof complies with such licenses and/or rights.

978-1-491-90399-5
[TI]

Table of Contents

From the Publisher. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi
Acknowledgments. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii
Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1. Deducing Types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Item 1:
Item 2:
Item 3:
Item 4:

Understand template type deduction.
Understand auto type deduction.
Understand decltype.
Know how to view deduced types.

9
18
23
30

2. auto. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Item 5: Prefer auto to explicit type declarations.
Item 6: Use the explicitly typed initializer idiom when auto deduces undesired types.

37
43

3. Moving to Modern C++. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Item 7: Distinguish between () and {} when creating objects.
Item 8: Prefer nullptr to 0 and NULL.
Item 9: Prefer alias declarations to typedefs.
Item 10: Prefer scoped enums to unscoped enums.
Item 11: Prefer deleted functions to private undefined ones.
Item 12: Declare overriding functions override.
Item 13: Prefer const_iterators to iterators.
Item 14: Declare functions noexcept if they won’t emit exceptions.
Item 15: Use constexpr whenever possible.

49
58
63
67
74
79
86
90
97 vii Item 16: Make const member functions thread safe.
Item 17: Understand special member function generation.

103
109

4. Smart Pointers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Item 18: Use std::unique_ptr for exclusive-ownership resource management. Item 19: Use std::shared_ptr for shared-ownership resource management. Item 20: Use std::weak_ptr for std::shared_ptr-like pointers that can dangle. Item 21: Prefer std::make_unique and std::make_shared to direct use of new. Item 22: When using the Pimpl Idiom, define special member functions in the implementation file.

118
125
134
139
147

5. Rvalue References, Move Semantics, and Perfect Forwarding. . . . . . . . . . . . . . . . . . . . 157
Item 23: Understand std::move and std::forward.
Item 24: Distinguish universal references from rvalue references.
Item 25: Use std::move on rvalue references, std::forward on universal references. Item 26: Avoid overloading on universal references.
Item 27: Familiarize yourself with alternatives to overloading on universal references. Item 28: Understand reference collapsing.
Item 29: Assume that move operations are not present, not cheap, and not used. Item 30: Familiarize yourself with perfect forwarding failure cases.

158
164
168
177
184
197
203
207

6. Lambda Expressions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Item 31:
Item 32:
Item 33:
Item 34:

Avoid default capture modes.
Use init capture to move objects into closures.
Use decltype on auto&& parameters to std::forward them.
Prefer lambdas to std::bind.

216
224
229
232

7. The Concurrency API. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
Item 35:
Item 36:
Item 37:
Item 38:
Item 39:

viii

|

Prefer task-based programming to thread-based.
Specify std::launch::async if asynchronicity is essential.
Make std::threads unjoinable on all paths.
Be aware of varying thread handle destructor behavior.
Consider void futures for one-shot event communication.

Table of Contents

241
245
250
258
262

Item 40: Use std::atomic for concurrency, volatile for special memory.

271

8. Tweaks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Item 41: Consider pass by value for copyable parameters that are cheap to move and always copied.
Item 42: Consider emplacement instead of insertion.

281
292

Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303

Table of Contents

|

ix

CHAPTER 1

Deducing Types

C++98 had a single set of rules for type deduction: the one for function templates.
C++11 modifies that ruleset a bit and adds two more, one for auto and one for decltype. C++14 then extends the usage contexts in which auto and decltype may be employed. The increasingly widespread application of type deduction frees you from the tyranny of spelling out types that are obvious or redundant. It makes C++ software more adaptable, because changing a type at one point in the source code automatically propagates through type deduction to other locations. However, it can render code more difficult to reason about, because the types deduced by compilers may not be as apparent as you’d like.
Without a solid understanding of how type deduction operates, effective program‐ ming in modern C++ is all but impossible. There are just too many contexts where type deduction takes place: in calls to function templates, in most situations where auto appears, in decltype expressions, and, as of C++14, where the enigmatic decltype(auto) construct is employed.
This chapter provides the information about type deduction that every C++ devel‐ oper requires. It explains how template type deduction works, how auto builds on that, and how decltype goes its own way. It even explains how you can force com‐ pilers to make the results of their type deductions visible, thus enabling you to ensure that compilers are deducing the types you want them to.

Item 1: Understand template type deduction.
When users of a complex system are ignorant of how it works, yet happy with what it does, that says a lot about the design of the system. By this measure, template type deduction in C++ is a tremendous success. Millions of programmers have passed
9

arguments to template functions with completely satisfactory results, even though many of those programmers would be hard-pressed to give more than the haziest description of how the types used by those functions were deduced.
If that group includes you, I have good news and bad news. The good news is that type deduction for templates is the basis for one of modern C++’s most compelling features: auto. If you were happy with how C++98 deduced types for templates, you’re set up to be happy with how C++11 deduces types for auto. The bad news is that when the template type deduction rules are applied in the context of auto, they sometimes seem less intuitive than when they’re applied to templates. For that rea‐ son, it’s important to truly understand the aspects of template type deduction that auto builds on. This Item covers what you need to know.
If you’re willing to overlook a pinch of pseudocode, we can think of a function tem‐ plate as looking like this: template void f(ParamType param);

A call can look like this: f(expr); // call f with some expression

During compilation, compilers use expr to deduce two types: one for T and one for
ParamType. These types are frequently different, because ParamType often contains adornments, e.g., const or reference qualifiers. For example, if the template is declared like this, template void f(const T& param);

// ParamType is const T&

and we have this call, int x = 0; f(x); // call f with an int

T is deduced to be int, but ParamType is deduced to be const int&.
It’s natural to expect that the type deduced for T is the same as the type of the argu‐ ment passed to the function, i.e., that T is the type of expr. In the above example, that’s the case: x is an int, and T is deduced to be int. But it doesn’t always work that way. The type deduced for T is dependent not just on the type of expr, but also on the form of ParamType. There are three cases:

10

|

Item 1

• ParamType is a pointer or reference type, but not a universal reference. (Univer‐ sal references are described in Item 24. At this point, all you need to know is that they exist and that they’re not the same as lvalue references or rvalue references.)
• ParamType is a universal reference.
• ParamType is neither a pointer nor a reference.
We therefore have three type deduction scenarios to examine. Each will be based on our general form for templates and calls to it: template void f(ParamType param); f(expr); // deduce T and ParamType from expr

Case 1: ParamType is a Reference or Pointer, but not a Universal
Reference
The simplest situation is when ParamType is a reference type or a pointer type, but not a universal reference. In that case, type deduction works like this:
1. If expr’s type is a reference, ignore the reference part.
2. Then pattern-match expr’s type against ParamType to determine T.
For example, if this is our template, template void f(T& param);

// param is a reference

and we have these variable declarations, int x = 27; const int cx = x; const int& rx = x;

// x is an int
// cx is a const int
// rx is a reference to x as a const int

the deduced types for param and T in various calls are as follows: f(x); // T is int, param's type is int&

f(cx);

// T is const int,
// param's type is const int&

f(rx);

// T is const int,
// param's type is const int&

Item 1

|

11

In the second and third calls, notice that because cx and rx designate const values, T is deduced to be const int, thus yielding a parameter type of const int&. That’s important to callers. When they pass a const object to a reference parameter, they expect that object to remain unmodifiable, i.e., for the parameter to be a reference-toconst. That’s why passing a const object to a template taking a T& parameter is safe: the constness of the object becomes part of the type deduced for T.
In the third example, note that even though rx’s type is a reference, T is deduced to be a non-reference. That’s because rx’s reference-ness is ignored during type deduc‐ tion. These examples all show lvalue reference parameters, but type deduction works exactly the same way for rvalue reference parameters. Of course, only rvalue argu‐ ments may be passed to rvalue reference parameters, but that restriction has nothing to do with type deduction.
If we change the type of f’s parameter from T& to const T&, things change a little, but not in any really surprising ways. The constness of cx and rx continues to be respec‐ ted, but because we’re now assuming that param is a reference-to-const, there’s no longer a need for const to be deduced as part of T: template void f(const T& param);

// param is now a ref-to-const

int x = 27; const int cx = x; const int& rx = x;

// as before
// as before
// as before

f(x);

// T is int, param's type is const int&

f(cx);

// T is int, param's type is const int&

f(rx);

// T is int, param's type is const int&

As before, rx’s reference-ness is ignored during type deduction.
If param were a pointer (or a pointer to const) instead of a reference, things would work essentially the same way: template void f(T* param); int x = 27; const int *px = &x;

12

// param is now a pointer
// as before
// px is a ptr to x as a const int

|

Item 1

f(&x);

// T is int, param's type is int*

f(px);

// T is const int,
// param's type is const int*

By now, you may find yourself yawning and nodding off, because C++’s type deduc‐ tion rules work so naturally for reference and pointer parameters, seeing them in written form is really dull. Everything’s just obvious! Which is exactly what you want in a type deduction system.

Case 2: ParamType is a Universal Reference
Things are less obvious for templates taking universal reference parameters. Such parameters are declared like rvalue references (i.e., in a function template taking a type parameter T, a universal reference’s declared type is T&&), but they behave differ‐ ently when lvalue arguments are passed in. The complete story is told in Item 24, but here’s the headline version:
• If expr is an lvalue, both T and ParamType are deduced to be lvalue references.
That’s doubly unusual. First, it’s the only situation in template type deduction where T is deduced to be a reference. Second, although ParamType is declared using the syntax for an rvalue reference, its deduced type is an lvalue reference.
• If expr is an rvalue, the “normal” (i.e., Case 1) rules apply.
For example: template void f(T&& param);

// param is now a universal reference

int x = 27; const int cx = x; const int& rx = x;

// as before
// as before
// as before

f(x);

// x is lvalue, so T is int&,
// param's type is also int&

f(cx);

// cx is lvalue, so T is const int&,
// param's type is also const int&

f(rx);

// rx is lvalue, so T is const int&,
// param's type is also const int&

f(27);

// 27 is rvalue, so T is int,
// param's type is therefore int&&

Item 1

|

13

Item 24 explains exactly why these examples play out the way they do. The key point here is that the type deduction rules for universal reference parameters are different from those for parameters that are lvalue references or rvalue references. In particu‐ lar, when universal references are in use, type deduction distinguishes between lvalue arguments and rvalue arguments. That never happens for non-universal references.

Case 3: ParamType is Neither a Pointer nor a Reference
When ParamType is neither a pointer nor a reference, we’re dealing with pass-byvalue: template void f(T param);

// param is now passed by value

That means that param will be a copy of whatever is passed in—a completely new object. The fact that param will be a new object motivates the rules that govern how T is deduced from expr:
1. As before, if expr’s type is a reference, ignore the reference part.
2. If, after ignoring expr’s reference-ness, expr is const, ignore that, too. If it’s volatile, also ignore that. (volatile objects are uncommon. They’re generally used only for implementing device drivers. For details, see Item 40.)
Hence:
int x = 27; const int cx = x; const int& rx = x;

// as before
// as before
// as before

f(x);

// T's and param's types are both int

f(cx);

// T's and param's types are again both int

f(rx);

// T's and param's types are still both int

Note that even though cx and rx represent const values, param isn’t const. That makes sense. param is an object that’s completely independent of cx and rx—a copy of cx or rx. The fact that cx and rx can’t be modified says nothing about whether param can be. That’s why expr’s constness (and volatileness, if any) is ignored when deducing a type for param: just because expr can’t be modified doesn’t mean that a copy of it can’t be.
It’s important to recognize that const (and volatile) is ignored only for by-value parameters. As we’ve seen, for parameters that are references-to- or pointers-toconst, the constness of expr is preserved during type deduction. But consider the
14

|

Item 1

case where expr is a const pointer to a const object, and expr is passed to a byvalue param: template void f(T param);

// param is still passed by value

const char* const ptr =
"Fun with pointers";

// ptr is const pointer to const object

f(ptr);

// pass arg of type const char * const

Here, the const to the right of the asterisk declares ptr to be const: ptr can’t be made to point to a different location, nor can it be set to null. (The const to the left of the asterisk says that what ptr points to—the character string—is const, hence can’t be modified.) When ptr is passed to f, the bits making up the pointer are copied into param. As such, the pointer itself (ptr) will be passed by value. In accord with the type deduction rule for by-value parameters, the constness of ptr will be ignored, and the type deduced for param will be const char*, i.e., a modifiable pointer to a const character string. The constness of what ptr points to is preserved during type deduction, but the constness of ptr itself is ignored when copying it to create the new pointer, param.

Array Arguments
That pretty much covers it for mainstream template type deduction, but there’s a niche case that’s worth knowing about. It’s that array types are different from pointer types, even though they sometimes seem to be interchangeable. A primary contribu‐ tor to this illusion is that, in many contexts, an array decays into a pointer to its first element. This decay is what permits code like this to compile: const char name[] = "J. P. Briggs";

// name's type is
// const char[13]

const char * ptrToName = name;

// array decays to pointer

Here, the const char* pointer ptrToName is being initialized with name, which is a const char[13]. These types (const char* and const char[13]) are not the same, but because of the array-to-pointer decay rule, the code compiles.
But what if an array is passed to a template taking a by-value parameter? What hap‐ pens then? template void f(T param);

// template with by-value parameter

Item 1

|

15

f(name);

// what types are deduced for T and param?

We begin with the observation that there is no such thing as a function parameter that’s an array. Yes, yes, the syntax is legal, void myFunc(int param[]);

but the array declaration is treated as a pointer declaration, meaning that myFunc could equivalently be declared like this: void myFunc(int* param);

// same function as above

This equivalence of array and pointer parameters is a bit of foliage springing from the
C roots at the base of C++, and it fosters the illusion that array and pointer types are the same.
Because array parameter declarations are treated as if they were pointer parameters, the type of an array that’s passed to a template function by value is deduced to be a pointer type. That means that in the call to the template f, its type parameter T is deduced to be const char*: f(name); // name is array, but T deduced as const char*

But now comes a curve ball. Although functions can’t declare parameters that are truly arrays, they can declare parameters that are references to arrays! So if we modify the template f to take its argument by reference, template void f(T& param);

// template with by-reference parameter

and we pass an array to it, f(name); // pass array to f

the type deduced for T is the actual type of the array! That type includes the size of the array, so in this example, T is deduced to be const char [13], and the type of f’s parameter (a reference to this array) is const char (&)[13]. Yes, the syntax looks toxic, but knowing it will score you mondo points with those few souls who care.
Interestingly, the ability to declare references to arrays enables creation of a template that deduces the number of elements that an array contains:
// return size of an array as a compile-time constant. (The
// array parameter has no name, because we care only about
// the number of elements it contains.) template // see info constexpr std::size_t arraySize(T (&)[N]) noexcept // below on
{
// constexpr

16

| Item 1

return N;

// and
// noexcept

}

As Item 15 explains, declaring this function constexpr makes its result available during compilation. That makes it possible to declare, say, an array with the same number of elements as a second array whose size is computed from a braced initial‐ izer: int keyVals[] = { 1, 3, 7, 9, 11, 22, 35 };

// keyVals has
// 7 elements

int mappedVals[arraySize(keyVals)];

// so does
// mappedVals

Of course, as a modern C++ developer, you’d naturally prefer a std::array to a built-in array: std::array mappedVals;

// mappedVals'
// size is 7

As for arraySize being declared noexcept, that’s to help compilers generate better code. For details, see Item 14.

Function Arguments
Arrays aren’t the only things in C++ that can decay into pointers. Function types can decay into function pointers, and everything we’ve discussed regarding type deduc‐ tion for arrays applies to type deduction for functions and their decay into function pointers. As a result: void someFunc(int, double);

// someFunc is a function;
// type is void(int, double)

template void f1(T param);

// in f1, param passed by value

template void f2(T& param);

// in f2, param passed by ref

f1(someFunc);

// param deduced as ptr-to-func;
// type is void (*)(int, double)

f2(someFunc);

// param deduced as ref-to-func;
// type is void (&)(int, double)

This rarely makes any difference in practice, but if you’re going to know about arrayto-pointer decay, you might as well know about function-to-pointer decay, too.
Item 1

|

17

So there you have it: the auto-related rules for template type deduction. I remarked at the outset that they’re pretty straightforward, and for the most part, they are. The special treatment accorded lvalues when deducing types for universal references muddies the water a bit, however, and the decay-to-pointer rules for arrays and func‐ tions stirs up even greater turbidity. Sometimes you simply want to grab your com‐ pilers and demand, “Tell me what type you’re deducing!” When that happens, turn to
Item 4, because it’s devoted to coaxing compilers into doing just that.

Things to Remember
• During template type deduction, arguments that are references are treated as non-references, i.e., their reference-ness is ignored.
• When deducing types for universal reference parameters, lvalue arguments get special treatment.
• When deducing types for by-value parameters, const and/or volatile argu‐ ments are treated as non-const and non-volatile.
• During template type deduction, arguments that are array or function names decay to pointers, unless they’re used to initialize references.

Item 2: Understand auto type deduction.
If you’ve read Item 1 on template type deduction, you already know almost every‐ thing you need to know about auto type deduction, because, with only one curious exception, auto type deduction is template type deduction. But how can that be?
Template type deduction involves templates and functions and parameters, but auto deals with none of those things.
That’s true, but it doesn’t matter. There’s a direct mapping between template type deduction and auto type deduction. There is literally an algorithmic transformation from one to the other.
In Item 1, template type deduction is explained using this general function template template void f(ParamType param);

and this general call: f(expr); // call f with some expression

In the call to f, compilers use expr to deduce types for T and ParamType.

18

|

Item 1

When a variable is declared using auto, auto plays the role of T in the template, and the type specifier for the variable acts as ParamType. This is easier to show than to describe, so consider this example: auto x = 27;

Here, the type specifier for x is simply auto by itself. On the other hand, in this decla‐ ration, const auto cx = x;

the type specifier is const auto. And here, const auto& rx = x;

the type specifier is const auto&. To deduce types for x, cx, and rx in these exam‐ ples, compilers act as if there were a template for each declaration as well as a call to that template with the corresponding initializing expression: template void func_for_x(T param);

// conceptual template for
// deducing x's type

func_for_x(27);

// conceptual call: param's
// deduced type is x's type

template void func_for_cx(const T param);

// conceptual template for
// deducing cx's type

func_for_cx(x);

// conceptual call: param's
// deduced type is cx's type

template void func_for_rx(const T& param);

// conceptual template for
// deducing rx's type

func_for_rx(x);

// conceptual call: param's
// deduced type is rx's type

As I said, deducing types for auto is, with only one exception (which we’ll discuss soon), the same as deducing types for templates.
Item 1 divides template type deduction into three cases, based on the characteristics of ParamType, the type specifier for param in the general function template. In a vari‐ able declaration using auto, the type specifier takes the place of ParamType, so there are three cases for that, too:
• Case 1: The type specifier is a pointer or reference, but not a universal reference.
• Case 2: The type specifier is a universal reference.
Item 2

|

19

• Case 3: The type specifier is neither a pointer nor a reference.
We’ve already seen examples of cases 1 and 3: auto x = 27;

// case 3 (x is neither ptr nor reference)

const auto cx = x;

// case 3 (cx isn't either)

const auto& rx = x;

// case 1 (rx is a non-universal ref.)

Case 2 works as you’d expect: auto&& uref1 = x;

// x is int and lvalue,
// so uref1's type is int&

auto&& uref2 = cx;

// cx is const int and lvalue,
// so uref2's type is const int&

auto&& uref3 = 27;

// 27 is int and rvalue,
// so uref3's type is int&&

Item 1 concludes with a discussion of how array and function names decay into pointers for non-reference type specifiers. That happens in auto type deduction, too: const char name[] =
"R. N. Briggs"; auto arr1 = name;

// arr1's type is const char*

auto& arr2 = name;

// arr2's type is
// const char (&)[13]

void someFunc(int, double);

// someFunc is a function;
// type is void(int, double)

auto func1 = someFunc;

// func1's type is
// void (*)(int, double)

auto& func2 = someFunc;

20

// name's type is const char[13]

// func2's type is
// void (&)(int, double)

|

Item 2

As you can see, auto type deduction works like template type deduction. They’re essentially two sides of the same coin.
Except for the one way they differ. We’ll start with the observation that if you want to declare an int with an initial value of 27, C++98 gives you two syntactic choices: int x1 = 27; int x2(27);

C++11, through its support for uniform initialization, adds these: int x3 = { 27 }; int x4{ 27 };

All in all, four syntaxes, but only one result: an int with value 27.
But as Item 5 explains, there are advantages to declaring variables using auto instead of fixed types, so it’d be nice to replace int with auto in the above variable declara‐ tions. Straightforward textual substitution yields this code: auto auto auto auto

x1 = 27; x2(27); x3 = { 27 }; x4{ 27 };

These declarations all compile, but they don’t have the same meaning as the ones they replace. The first two statements do, indeed, declare a variable of type int with value 27. The second two, however, declare a variable of type std::initial izer_list containing a single element with value 27! auto x1 = 27;

// type is int, value is 27

auto x2(27);

// ditto

auto x3 = { 27 };

// type is std::initializer_list,
// value is { 27 }

auto x4{ 27 };

// ditto

This is due to a special type deduction rule for auto. When the initializer for an auto-declared variable is enclosed in braces, the deduced type is a std::initial izer_list. If such a type can’t be deduced (e.g., because the values in the braced ini‐ tializer are of different types), the code will be rejected: auto x5 = { 1, 2, 3.0 };

// error! can't deduce T for
// std::initializer_list

Item 2

|

21

As the comment indicates, type deduction will fail in this case, but it’s important to recognize that there are actually two kinds of type deduction taking place. One kind stems from the use of auto: x5’s type has to be deduced. Because x5’s initializer is in braces, x5 must be deduced to be a std::initializer_list. But std::initial izer_list is a template. Instantiations are std::initializer_list for some type T, and that means that T’s type must also be deduced. Such deduction falls under the purview of the second kind of type deduction occurring here: template type deduction. In this example, that deduction fails, because the values in the braced ini‐ tializer don’t have a single type.
The treatment of braced initializers is the only way in which auto type deduction and template type deduction differ. When an auto–declared variable is initialized with a braced initializer, the deduced type is an instantiation of std::initializer_list.
But if the corresponding template is passed the same initializer, type deduction fails, and the code is rejected: auto x = { 11, 23, 9 };

// x's type is
// std::initializer_list

template void f(T param);

// template with parameter
// declaration equivalent to
// x's declaration

f({ 11, 23, 9 });

// error! can't deduce type for T

However, if you specify in the template that param is a std::initializer_list for some unknown T, template type deduction will deduce what T is: template void f(std::initializer_list initList); f({ 11, 23, 9 });

// T deduced as int, and initList's
// type is std::initializer_list

So the only real difference between auto and template type deduction is that auto assumes that a braced initializer represents a std::initializer_list, but template type deduction doesn’t.
You might wonder why auto type deduction has a special rule for braced initializers, but template type deduction does not. I wonder this myself. Alas, I have not been able to find a convincing explanation. But the rule is the rule, and this means you must remember that if you declare a variable using auto and you initialize it with a braced initializer, the deduced type will always be std::initializer_list. It’s especially important to bear this in mind if you embrace the philosophy of uniform initializa‐ tion—of enclosing initializing values in braces as a matter of course. A classic mistake
22

| Item 2

in C++11 programming is accidentally declaring a std::initializer_list variable when you mean to declare something else. This pitfall is one of the reasons some developers put braces around their initializers only when they have to. (When you have to is discussed in Item 7.)
For C++11, this is the full story, but for C++14, the tale continues. C++14 permits auto to indicate that a function’s return type should be deduced (see Item 3), and
C++14 lambdas may use auto in parameter declarations. However, these uses of auto employ template type deduction, not auto type deduction. So a function with an auto return type that returns a braced initializer won’t compile: auto createInitList()
{
return { 1, 2, 3 };
}

// error: can't deduce type
// for { 1, 2, 3 }

The same is true when auto is used in a parameter type specification in a C++14 lambda: std::vector v;

auto resetV =
[&v](const auto& newValue) { v = newValue; };

// C++14

… resetV({ 1, 2, 3 });

// error! can't deduce type
// for { 1, 2, 3 }

Things to Remember
• auto type deduction is usually the same as template type deduction, but auto type deduction assumes that a braced initializer represents a std::initial izer_list, and template type deduction doesn’t.
• auto in a function return type or a lambda parameter implies template type deduction, not auto type deduction.

Item 3: Understand decltype. decltype is an odd creature. Given a name or an expression, decltype tells you the name’s or the expression’s type. Typically, what it tells you is exactly what you’d

Item 2

|

23

predict. Occasionally however, it provides results that leave you scratching your head and turning to reference works or online Q&A sites for revelation.
We’ll begin with the typical cases—the ones harboring no surprises. In contrast to what happens during type deduction for templates and auto (see Items 1 and 2), decltype typically parrots back the exact type of the name or expression you give it: const int i = 0;

// decltype(i) is const int

bool f(const Widget& w);

// decltype(w) is const Widget&
// decltype(f) is bool(const Widget&)

struct Point { int x, y;
};

// decltype(Point::x) is int
// decltype(Point::y) is int

Widget w;

// decltype(w) is Widget

if (f(w)) …

// decltype(f(w)) is bool

template
// simplified version of std::vector class vector { public: …
T& operator[](std::size_t index);

}; vector v;

if (v[0] == 0) …

// decltype(v) is vector
// decltype(v[0]) is int&

See? No surprises.
In C++11, perhaps the primary use for decltype is declaring function templates where the function’s return type depends on its parameter types. For example, sup‐ pose we’d like to write a function that takes a container that supports indexing via square brackets (i.e., the use of “[]”) plus an index, then authenticates the user before returning the result of the indexing operation. The return type of the function should be the same as the type returned by the indexing operation. operator[] on a container of objects of type T typically returns a T&. This is the case for std::deque, for example, and it’s almost always the case for std::vector. For std::vector, however, operator[] does not return a bool&. Instead, it returns a brand new object. The whys and hows of this situation are explored in

24

|

Item 3

Item 6, but what’s important here is that the type returned by a container’s opera tor[] depends on the container. decltype makes it easy to express that. Here’s a first cut at the template we’d like to write, showing the use of decltype to compute the return type. The template needs a bit of refinement, but we’ll defer that for now: template auto authAndAccess(Container& c, Index i)
-> decltype(c[i])
{
authenticateUser(); return c[i];
}

// works, but
// requires
// refinement

The use of auto before the function name has nothing to do with type deduction.
Rather, it indicates that C++11’s trailing return type syntax is being used, i.e., that the function’s return type will be declared following the parameter list (after the “->”). A trailing return type has the advantage that the function’s parameters can be used in the specification of the return type. In authAndAccess, for example, we specify the return type using c and i. If we were to have the return type precede the function name in the conventional fashion, c and i would be unavailable, because they would not have been declared yet.
With this declaration, authAndAccess returns whatever type operator[] returns when applied to the passed-in container, exactly as we desire.
C++11 permits return types for single-statement lambdas to be deduced, and C++14 extends this to both all lambdas and all functions, including those with multiple statements. In the case of authAndAccess, that means that in C++14 we can omit the trailing return type, leaving just the leading auto. With that form of declaration, auto does mean that type deduction will take place. In particular, it means that com‐ pilers will deduce the function’s return type from the function’s implementation: template auto authAndAccess(Container& c, Index i)
{
authenticateUser(); return c[i];
// return type
}

// C++14;
// not quite
// correct deduced from c[i]

Item 2 explains that for functions with an auto return type specification, compilers employ template type deduction. In this case, that’s problematic. As we’ve discussed, operator[] for most containers-of-T returns a T&, but Item 1 explains that during

Item 3

|

25

template type deduction, the reference-ness of an initializing expression is ignored.
Consider what that means for this client code: std::deque d;

authAndAccess(d, 5) = 10;

// authenticate user, return d[5],
// then assign 10 to it;
// this won't compile!

Here, d[5] returns an int&, but auto return type deduction for authAndAccess will strip off the reference, thus yielding a return type of int. That int, being the return value of a function, is an rvalue, and the code above thus attempts to assign 10 to an rvalue int. That’s forbidden in C++, so the code won’t compile.
To get authAndAccess to work as we’d like, we need to use decltype type deduction for its return type, i.e., to specify that authAndAccess should return exactly the same type that the expression c[i] returns. The guardians of C++, anticipating the need to use decltype type deduction rules in some cases where types are inferred, make this possible in C++14 through the decltype(auto) specifier. What may initially seem contradictory (decltype and auto?) actually makes perfect sense: auto specifies that the type is to be deduced, and decltype says that decltype rules should be used during the deduction. We can thus write authAndAccess like this: template decltype(auto) authAndAccess(Container& c, Index i)
{
authenticateUser(); return c[i];
}

//
//
//
//

C++14; works, but still requires refinement

Now authAndAccess will truly return whatever c[i] returns. In particular, for the common case where c[i] returns a T&, authAndAccess will also return a T&, and in the uncommon case where c[i] returns an object, authAndAccess will return an object, too.
The use of decltype(auto) is not limited to function return types. It can also be convenient for declaring variables when you want to apply the decltype type deduc‐ tion rules to the initializing expression:
Widget w; const Widget& cw = w; auto myWidget1 = cw;

26

|

Item 3

// auto type deduction:

// myWidget1's type is Widget decltype(auto) myWidget2 = cw;

// decltype type deduction:
// myWidget2's type is
//
const Widget&

But two things are bothering you, I know. One is the refinement to authAndAccess I mentioned, but have not yet described. Let’s address that now.
Look again at the declaration for the C++14 version of authAndAccess: template decltype(auto) authAndAccess(Container& c, Index i);

The container is passed by lvalue-reference-to-non-const, because returning a refer‐ ence to an element of the container permits clients to modify that container. But this means it’s not possible to pass rvalue containers to this function. Rvalues can’t bind to lvalue references (unless they’re lvalue-references-to-const, which is not the case here). Admittedly, passing an rvalue container to authAndAccess is an edge case. An rvalue container, being a temporary object, would typically be destroyed at the end of the statement containing the call to authAndAccess, and that means that a reference to an element in that container (which is typically what authAndAccess would return) would dangle at the end of the statement that created it. Still, it could make sense to pass a temporary object to authAndAccess. A client might simply want to make a copy of an element in the temporary container, for example: std::deque makeStringDeque();

// factory function

// make copy of 5th element of deque returned
// from makeStringDeque auto s = authAndAccess(makeStringDeque(), 5);

Supporting such use means we need to revise the declaration for authAndAccess to accept both lvalues and rvalues. Overloading would work (one overload would declare an lvalue reference parameter, the other an rvalue reference parameter), but then we’d have two functions to maintain. A way to avoid that is to have authAndAc cess employ a reference parameter that can bind to lvalues and rvalues, and Item 24 explains that that’s exactly what universal references do. authAndAccess can there‐ fore be declared like this: template decltype(auto) authAndAccess(Container&& c,
Index i);

// c is now a
// universal
// reference

Item 3

|

27

In this template, we don’t know what type of container we’re operating on, and that means we’re equally ignorant of the type of index objects it uses. Employing pass-byvalue for objects of an unknown type generally risks the performance hit of unneces‐ sary copying, the behavioral problems of object slicing (see Item 41), and the sting of our coworkers’ derision, but in the case of container indices, following the example of the Standard Library for index values (e.g., in operator[] for std::string, std::vector, and std::deque) seems reasonable, so we’ll stick with pass-by-value for them.
However, we need to update the template’s implementation to bring it into accord with Item 25’s admonition to apply std::forward to universal references: template decltype(auto) authAndAccess(Container&& c, Index i)
{
authenticateUser(); return std::forward(c)[i];
}

// final
// C++14
// version

This should do everything we want, but it requires a C++14 compiler. If you don’t have one, you’ll need to use the C++11 version of the template. It’s the same as its
C++14 counterpart, except that you have to specify the return type yourself: template auto authAndAccess(Container&& c, Index i)
-> decltype(std::forward(c)[i])
{
authenticateUser(); return std::forward(c)[i];
}

// final
// C++11
// version

The other issue that’s likely to be nagging at you is my remark at the beginning of this
Item that decltype almost always produces the type you expect, that it rarely sur‐ prises. Truth be told, you’re unlikely to encounter these exceptions to the rule unless you’re a heavy-duty library implementer.
To fully understand decltype’s behavior, you’ll have to familiarize yourself with a few special cases. Most of these are too obscure to warrant discussion in a book like this, but looking at one lends insight into decltype as well as its use.
Applying decltype to a name yields the declared type for that name. Names are lvalue expressions, but that doesn’t affect decltype’s behavior. For lvalue expressions more complicated than names, however, decltype ensures that the type reported is
28

|

Item 3

always an lvalue reference. That is, if an lvalue expression other than a name has type
T, decltype reports that type as T&. This seldom has any impact, because the type of most lvalue expressions inherently includes an lvalue reference qualifier. Functions returning lvalues, for example, always return lvalue references.
There is an implication of this behavior that is worth being aware of, however. In int x = 0;

x is the name of a variable, so decltype(x) is int. But wrapping the name x in parentheses—“(x)”—yields an expression more complicated than a name. Being a name, x is an lvalue, and C++ defines the expression (x) to be an lvalue, too. decltype((x)) is therefore int&. Putting parentheses around a name can change the type that decltype reports for it!
In C++11, this is little more than a curiosity, but in conjunction with C++14’s sup‐ port for decltype(auto), it means that a seemingly trivial change in the way you write a return statement can affect the deduced type for a function: decltype(auto) f1()
{
int x = 0;

return x;
// decltype(x) is int, so f1 returns int
}
decltype(auto) f2()
{
int x = 0;

return (x);
// decltype((x)) is int&, so f2 returns int&
}

Note that not only does f2 have a different return type from f1, it’s also returning a reference to a local variable! That’s the kind of code that puts you on the express train to undefined behavior—a train you certainly don’t want to be on.
The primary lesson is to pay very close attention when using decltype(auto).
Seemingly insignificant details in the expression whose type is being deduced can affect the type that decltype(auto) reports. To ensure that the type being deduced is the type you expect, use the techniques described in Item 4.
At the same time, don’t lose sight of the bigger picture. Sure, decltype (both alone and in conjunction with auto) may occasionally yield type-deduction surprises, but that’s not the normal situation. Normally, decltype produces the type you expect.

Item 3

|

29

This is especially true when decltype is applied to names, because in that case, decltype does just what it sounds like: it reports that name’s declared type.

Things to Remember
• decltype almost always yields the type of a variable or expression without any modifications.
• For lvalue expressions of type T other than names, decltype always reports a type of T&.
• C++14 supports decltype(auto), which, like auto, deduces a type from its initializer, but it performs the type deduction using the decltype rules.

Item 4: Know how to view deduced types.
The choice of tools for viewing the results of type deduction is dependent on the phase of the software development process where you want the information. We’ll explore three possibilities: getting type deduction information as you edit your code, getting it during compilation, and getting it at runtime.

IDE Editors
Code editors in IDEs often show the types of program entities (e.g., variables, param‐ eters, functions, etc.) when you do something like hover your cursor over the entity.
For example, given this code, const int theAnswer = 42; auto x = theAnswer; auto y = &theAnswer;

an IDE editor would likely show that x’s deduced type was int and y’s was const int*. For this to work, your code must be in a more or less compilable state, because what makes it possible for the IDE to offer this kind of information is a C++ compiler (or at least the front end of one) running inside the IDE. If that compiler can’t make enough sense of your code to parse it and perform type deduction, it can’t show you what types it deduced.
For simple types like int, information from IDEs is generally fine. As we’ll see soon, however, when more complicated types are involved, the information displayed by
IDEs may not be particularly helpful.

30

|

Item 3

Compiler Diagnostics
An effective way to get a compiler to show a type it has deduced is to use that type in a way that leads to compilation problems. The error message reporting the problem is virtually sure to mention the type that’s causing it.
Suppose, for example, we’d like to see the types that were deduced for x and y in the previous example. We first declare a class template that we don’t define. Something like this does nicely: template class TD;

// declaration only for TD;
// TD == "Type Displayer"

Attempts to instantiate this template will elicit an error message, because there’s no template definition to instantiate. To see the types for x and y, just try to instantiate
TD with their types:
TD xType;
TD yType;

// elicit errors containing
// x's and y's types

I use variable names of the form variableNameType, because they tend to yield error messages that help me find the information I’m looking for. For the code above, one of my compilers issues diagnostics reading, in part, as follows (I’ve highlighted the type information we’re after): error: aggregate 'TD xType' has incomplete type and cannot be defined error: aggregate 'TD yType' has incomplete type and cannot be defined

A different compiler provides the same information, but in a different form: error: 'xType' uses undefined class 'TD' error: 'yType' uses undefined class 'TD'

Formatting differences aside, all the compilers I’ve tested produce error messages with useful type information when this technique is employed.

Runtime Output
The printf approach to displaying type information (not that I’m recommending you use printf) can’t be employed until runtime, but it offers full control over the formatting of the output. The challenge is to create a textual representation of the type you care about that is suitable for display. “No sweat,” you’re thinking, “it’s typeid and std::type_info::name to the rescue.” In our continuing quest to see the types deduced for x and y, you may figure we can write this:

Item 4

|

31

std::cout

Similar Documents

Free Essay

God of War

...The Caldera Cont. [W-07.2] == Once back at the Caldera, open the SPECIAL CHEST that contains a GORGON EYE and use your Fire Blades to break the gears holding the archimedean screw together. You may now backtrack to that new type of door you saw earlier, and break it down. Inside grab the GREEN CHEST and a RED CHEST before continuing along the path. When you slide down the next ramp you'll land onto a platform where you have to face two Minotaurs and some firebirds. Grab the BLUE/GREEN CHEST and then pull the lever here. Jump onto the lava rock and you will float along the lava flow. You will fight a small wave of fire crab-spiders before eventually needing to jump onto a wall as the lava rock begins to burn away. At the top open the SPECIAL CHEST that contains a MINOTAUR HORN and be sure to save at the Save Point. Sidle your way across the ledge to your right then break the gears on another one of the archimedean screws. Climb up the ledge here and keep moving. At the end of the path open both the GREEN CHEST and BLUE CHEST before breaking down another fire door. Open the SPECIAL CHEST and sidle your way through the crevice here and around into the Volcano Core. _______________________________________________________________________________ | NOTE: If you find all the SPECIAL CHESTS some will only contain Orbs, but if| | you miss some, the others will compensate. | |_____________________________________________________________________________| Before you can get completely around...

Words: 6252 - Pages: 26

Premium Essay

God of War

...ICT Evaluation Logo: The purpose of the logo was to represent my Community Spirit Event to make it stand out from other event. It is luminously coloured to attract audiences from all ages from children to elders. It is easy and catchy to remember by everyone as it represents community spirit as a whole. Also my image of a ‘handshake’ symbolises that we are welcoming them to community spirit. I had to change the colour of the writing from ‘green’ to ‘red’ as it didn’t look appropriate and suit the image of my logo. Also I had to change my image from a ‘rainbow’ to ‘handshake’ because the image wasn’t a copyright free image. A way I could improve further would be make a series of logos and do a vote or survey on which one they find more appealing. Also I could’ve used different softwares like Maya or Cinema 4D to create my logo as it would’ve made it more attractive, instead of using fireworks. Track List: The purpose of the track list was to organize music tracks in order and also to help organise them to make finding the track easier than if it was not in alphabetic order. I had to produce several tack lists as most the time they was either too long or too small or the colour text and theme of the list didn’t look right when viewed in a PDF type of file. Audio Clip: The purpose of having an audio clip was to notify people of my event so that it would attract people to come and visit. It includes the time and date, location, events and what’s taking place without telling...

Words: 1418 - Pages: 6

Premium Essay

Nike And Ares: The Greek God Of War

...What you don’t know won’t hurt. Nike and Ares are both gods, Nike is the god of Victory. Ares is the god of war. They were the bestest of friends, and honestly Nike and Ares kinda go hand in hand because Ares is the god of war, and Nike is the god of victory, and who wouldn't want to win the war. Nike had a weird feeling, kinda like when you're not feeling good. This went on for a couple weeks before he told Ares. Immediately Ares told Nike ‘’You need to go to the doctor. Ares even offered to take Nike, ‘’NO!’’ he refused. Nike went to the doctor the next day. The doctor had a concern about something on his lungs and wanted to do some testing. Nike was worried of what the doctor was concerned about. The doctor didn’t tell...

Words: 302 - Pages: 2

Premium Essay

Greek God Of War Research Paper

...Ares, the god of war, represents the more violent and bloody aspects of war (Jordan 28). Ares revels in warfare, not caring who wins or loses as long as a lot of blood is shed (D’Aulaire 32). Ares is vain and cruel; described by Zeus as “the most hateful of gods” (D’Aulaire 32; Jordan 28). Ares’ sons, Deimos and Phobos, are even more barbaric than he is (Jordan 28). He is described by Homer as murderous and bloodstained, yet also a coward (Hamilton 34). Ares can not bear pain and when he was wounded would scream so loudly he could be heard for miles (D’Aulaire 32). Despite Ares being the god of war, he is not the best fighter among the gods; Athena would often beat him with her intelligence alone and he occasionally lost in hand to hand combat (Devambez 52). Ares is depicted as tall and handsome, wearing a helmet and armed with a spear and...

Words: 747 - Pages: 3

Premium Essay

Gods Personify Us

...Gods Personify Us “We everlasting gods… Ah what chilling blows we suffer-thanks to our own conflicting wills-whenever we show there moral men some kindness’’ It is obvious that the gods and goddesses are very important in traditional Greek Culture. The whole cause of the Trojan War is based around the fact that even gods can feel emotions such as jealousy, anger and vengeance. The gods are used by Homer to add twists on an otherwise standard plot of war. During the epic, there are times when gods and goddesses alike influence the war by infuriating the soldiers in order to have them continue fighting. Other times, some gods or goddesses removed certain characters so as to avoid death. The gods do not maintain order among humans nor among themselves. They are at times completely selfish and the ones who mostly suffer the consequences of their selfish meddling are the mortals. The mortals pray to and make sacrifices to the gods, yet do not fully understand that their lives are in the hands of fate and fate alone.  The gods’ actions are never a result of what is just or fair. They are not interested in the good of anyone, but only in their personal interests. In furthering their interests they use whatever mortals serve their purpose. The gods dabble in the life of man and routinely thwart any attempt for him to entirely forge his own future. The mortals in question are necessary only in so far as their use to the gods and when the gods will or desire is achieved; the...

Words: 1438 - Pages: 6

Premium Essay

The Role of the Gods in the Iliad

...reflects this. Nearly all of the Greek gods are involved in the outcome of the Trojan War, which happens to be the background story of this epic poem. The gods are used by Homer to add twists on an otherwise standard plot of war. Evidently, the gods will be a powerful source of divine intervention and their actions certainly have significant outcomes on the Trojan War, and more importantly, the story of The Iliad. Zeus, very untypical of a Greek god in his lack of involvement in the Trojan War for selfish reasons, was portrayed as the father figure, being impartial and fair to both sides of the war. He remains this way to serve as a check for the other god's involvement in the war. Without the presence of fate controlling the inner circle of Olympus, it is likely that the activity of the Trojan War would have become chaotic, possibly even becoming a playground of war for the gods. The power of fate, above all of the other gods combined, is a power that not even divine intervention can prevent. This theme of fate and how it controls the god’s actions is quite befitting to the storyline of The Iliad. The Iliad, in essence, recounts the story of part of the tenth year of the Trojan War. It recounts of the anger of Achilles, the greatest warrior present at Troy, and of the background battle that is ensuing. The reoccurring theme in the Iliad is that no matter whom the character is, god or human, they are bound to their fate, and it is the gods who must be the mediators and deliverers...

Words: 3197 - Pages: 13

Premium Essay

Iliad Gods Vs Humans

...Do you believe that gods are morally superior to humans? In the Iliad there is a very complex relationship between the gods and the humans. One would commonly believe that the gods help the humans stay moral, however in the Iliad it is almost the exact opposite. This essay, through textual evidence as well as through arguments from authority, will show how the gods are in fact less moral than the humans. Often those who start or refuse to stop an unjust war are considered to be immoral people, or in the case of the Iliad as immoral gods. According to Stanford Encyclopedia of Philosophy on War, “War can be necessary and proportionate only if it serves an end worth all this death and destruction” (Lazar 3.1). Meaning war may be needed if there is a just reason and if the war will prevent even more catastrophe. The gods in the Iliad time and time again act immoral by provoking unjust wars and frequently encouraging wars to continue that are coming to an end, such as when Athena "stirs" the fighting at the wishes of Zeus, Zeus telling Athena to "Urge on the Danaans" (Book 17, 537-543). In the Iliad each god has their own self-serving plan for what they wish to happen and every one of them uses the...

Words: 1072 - Pages: 5

Free Essay

Be Still

...Psalms 46:6-11; ; . War and peace depend on his word and will, as much as storms and calms at sea do, Ps 107:25,29. He makes wars to cease unto the end of the earth, sometimes in pity to the nations, that they may have a breathing-time, when, by long wars with each other, they have run themselves out of breadth. Both sides perhaps are weary of the war, and willing to let it fall; expedients are found out for accommodation; martial princes are removed, and peace-makers set in their room; and then the bow is broken by consent, the spear cut asunder and turned into a pruning-hook, the sword beaten into a ploughshare, and the chariots of war are burned, there being no more occasion for them; or, rather, it may be meant of what he does, at other times, in favour of his own people. He makes those wars to cease that were waged against them and designed for their ruin. He breaks the enemies' bow that was drawn against them. No weapon formed against Zion shall prosper, Isa 54:17. The total destruction of Gog and Magog is prophetically described by the burning of their weapons of war (Ezek 39:9,10), which intimates likewise the church's perfect security and assurance of lasting peace, which made it needless to lay up those weapons of war for their own service. The bringing of a long war to a good issue is a work of the Lord, which we ought to behold with wonder and thankfulness. II. As King of saints, and as such we must own that great and marvellous are his works, Rev 15:3. He does...

Words: 7358 - Pages: 30

Premium Essay

What Role Does Fate Play In The Iliad

...Outcome? The outcome of the war: Is it controlled by the actions of mere mortals? Do the gods determine the successes and failures? Is the outcome solely a matter of fate? Some may believe that mortals have free will, but after a quick skim of the Iliad, this belief is clearly shown to be false. Humans are not given control over their destinies; however, if this is true, then what are these destinies controlled by? Fate seems to be the only answer, yet, can fate alone stop a god from changing outcomes for their personal gain? In the Iliad, gods and humans are shown to have a varying degree of control on the outcome of human life and death. The true controller of the outcome of success vs. failure, and life vs. death, will be analyzed with...

Words: 959 - Pages: 4

Premium Essay

The Gods

...The Role of the Gods in the Iliad In the era of Homer, divine intervention was thought to be typical, and one of his foremost works, The Iliad, reflects this. Nearly all of the Greek gods are involved in the outcome of the Trojan War, which happens to be the background story of this epic poem. The gods are used by Homer to add twists on an otherwise standard plot of war. Evidently, the gods will be a powerful source of divine intervention and their actions certainly have significant outcomes on the Trojan War, and more importantly, the story of The Iliad. Zeus, very untypical of a Greek god in his lack of involvement in the Trojan War for selfish reasons, was portrayed as the father figure, being impartial and fair to both sides of the war. He remains this way to serve as a check for the other god's involvement in the war. Without the presence of fate controlling the inner circle of Olympus, it is likely that the activity of the Trojan War would have become chaotic, possibly even becoming a playground of war for the gods. The power of fate, above all of the other gods combined, is a power that not even divine intervention can prevent. This theme of fate and how it controls the god’s actions is quite befitting to the storyline of The Iliad. The Iliad, in essence, recounts the story of part of the tenth year of the Trojan War. It recounts of the anger of Achilles, the greatest warrior present at Troy, and of the background battle that is ensuing. The reoccurring theme in the Iliad...

Words: 370 - Pages: 2

Premium Essay

Iliad

...The Role of the Gods in the Iliad In the era of Homer, divine intervention was thought to be typical, and one of his foremost works, The Iliad, reflects this. Nearly all of the Greek gods are involved in the outcome of the Trojan War, which happens to be the background story of this epic poem. The gods are used by Homer to add twists on an otherwise standard plot of war. Evidently, the gods will be a powerful source of divine intervention and their actions certainly have significant outcomes on the Trojan War, and more importantly, the story of The Iliad. Zeus, very untypical of a Greek god in his lack of involvement in the Trojan War for selfish reasons, was portrayed as the father figure, being impartial and fair to both sides of the war. He remains this way to serve as a check for the other god's involvement in the war. Without the presence of fate controlling the inner circle of Olympus, it is likely that the activity of the Trojan War would have become chaotic, possibly even becoming a playground of war for the gods. The power of fate, above all of the other gods combined, is a power that not even divine intervention can prevent. This theme of fate and how it controls the god’s actions is quite befitting to the storyline of The Iliad. The Iliad, in essence, recounts the story of part of the tenth year of the Trojan War. It recounts of the anger of Achilles, the greatest warrior present at Troy, and of the background battle that is ensuing. The reoccurring theme in the Iliad...

Words: 370 - Pages: 2

Free Essay

This Things

...factors. First, the major factors that aided in shift of the decline. What effect did the “Thirty Year War’ have on the overall decline of European Christianity. What effect did “The Thirty Year War” have concerning religious commitment and civil and political concerning life? Then I will focus on other factors that brought Europeans Christianity to the point that it came to in the past, and look at other factors as well. Finally, I will paint a clear picture as to the effect of all the concerns that I have taken place (years of war), and look to see the positive and the negative effect all the different changes has brought. Wars of Religion These wars set the stage regarding the progress and the decline regarding Christianity, one would think that this form of action (War) would somehow aid in the advancement of Christianity (this not the case). Then religious values were regarded as of primary concern. The great thinkers on political and economic subjects usually based their ideas on religious principles. The major wars were Wars of Religion.[1] As we read from the above statement, the religious values are a major concern, even to the point that war would breakout. So it is of these values that war wages forth, but the wars that should have aided in bringing the thought of religious ideas, has brought about “The war of Religion”. It was thought that through these wars...

Words: 1681 - Pages: 7

Premium Essay

Was Abraham Lincoln Right Or Wrong

...beginning of the war, Abraham Lincoln felt as though the purpose of the war was to determine right and wrong and he believed that God couldn’t be on both sides. Both sides had biblical evidence that one was right while the other was wrong, but it wasn’t possible for both sides to be correct. Eventually there would have to be a winner and there would have to be a loser. Lincoln did not want the nation to go to war though, and he certainly did not want the nation to divide. He tried to reason with both the north and the south through the Emancipation and he had wanted to find some sort of compromise as opposed to fighting and he knew that too many lives would be lost in such a war. But all was in vain; there was no compromise to be made and lives were to be lost....

Words: 706 - Pages: 3

Premium Essay

Bob Dylan Pacifism

...his song “with god on our side”. This song was considered one of Bob Dylan’s most influential songs. In the song the main topic is war, he explains that god is on our side during war but he doesn’t seem to understand the reasoning of the war in the first place but he realizes that we must accept it. After learning about this song I looked up multiple sources on questions that bob Dylan is asking in this song such as why is there war? Why should we accept it? These sources that I have looked up are very useful to gather more information on the main topic of this song. I found 4 articles that talk about war and explaining reasoning behind war. The first article that I used was an article called “Why is...

Words: 1027 - Pages: 5

Premium Essay

Baal Apologists: Asking With Incorrect Motive

... Asking with Incorrect Motive. God does not answer prayers when the prayer is praying with incorrect motives. Thus, according to Baal apologists, Baal’s priest did not lose because Jehovah is mightier; they lost because they prayed with an incorrect motive. Therefore, Baal did not answer their prayers and allowed Elijah to win. Thus, of the multitude who pray for peace, none ask with the correct motive. Of the few who pray for war, at least one asks with the correct motive. Therefore, as we have war instead of peace. Apparently, a desire for war is the correct motive, while a desire for peace is an incorrect motive. 32. Asking from a Selfish Heart. God does not answer prayers of a prayer who prays from a selfish heart. Thus, according...

Words: 449 - Pages: 2