Type Inference auto for Note: Note:

Similar documents
I m sure you have been annoyed at least once by having to type out types like this:

2 is type double 3 auto i = 1 + 2; // evaluates to an 4 integer, so it is int. 1 auto d = 5.0; // 5.0 is a double literal, so it

Auto - a necessary evil?

Introduction to Move Semantics in C++ C and C

Implicit Evaluation of auto Variables and Arguments

Implicit Evaluation of auto Variables and Arguments

Declaration Syntax. Declarations. Declarators. Declaration Specifiers. Declaration Examples. Declaration Examples. Declarators include:

C++11/14 Rocks. Clang Edition. Alex Korban

Lesson 13 - Vectors Dynamic Data Storage

QUIZ. What is wrong with this code that uses default arguments?

C The new standard

Decltype (revision 6): proposed wording

New wording for C++0x Lambdas

PIC 10A Objects/Classes

Fast Introduction to Object Oriented Programming and C++

Object-Oriented Principles and Practice / C++

And Even More and More C++ Fundamentals of Computer Science

Type Aliases. Examples: using newtype = existingtype; // C++11 typedef existingtype newtype; // equivalent, still works

Templating functions. Comp Sci 1570 Introduction to C++ Administrative notes. Review. Templates. Compiler processing. Functions Overloading

AIMS Embedded Systems Programming MT 2017

C++ for numerical computing - part 2

C++11 and Compiler Update

Expansion statements. Version history. Introduction. Basic usage

These new operators are intended to remove some of the holes in the C type system introduced by the old C-style casts.

Object-Oriented Programming

Overview. 1. Expression Value Categories 2. Rvalue References 3. Templates 4. Miscellaneous Hilarity 2/43

G52CPP C++ Programming Lecture 20

A brief introduction to C++

C++11 Introduction to the New Standard. Alejandro Cabrera February 1, 2012 Florida State University Department of Computer Science

Outline. 1 About the course

CS

Concepts syntax and composition

Ch. 12: Operator Overloading

Appendix. Grammar. A.1 Introduction. A.2 Keywords. There is no worse danger for a teacher than to teach words instead of things.

Constructors for classes

Cpt S 122 Data Structures. Templates

Modern C++ for Computer Vision and Image Processing. Igor Bogoslavskyi

Lecture 10: building large projects, beginning C++, C++ and structs

Lambda Correctness and Usability Issues

Part X. Advanced C ++

When we program, we have to deal with errors. Our most basic aim is correctness, but we must

Deducing the type of variable from its initializer expression (revision 3)

Lecture 8. Exceptions, Constructor, Templates TDDD86: DALP. Content. Contents Exceptions

CS 251 INTERMEDIATE SOFTWARE DESIGN SPRING C ++ Basics Review part 2 Auto pointer, templates, STL algorithms

1/29/2011 AUTO POINTER (AUTO_PTR) INTERMEDIATE SOFTWARE DESIGN SPRING delete ptr might not happen memory leak!

std::optional from Scratch

TDDD38 - Advanced programming in C++

An Introduction to C++

Lecture Topics. Administrivia

Deducing the type of variable from its initializer expression (revision 4)

Programming 2. Object Oriented Programming. Daniel POP

Elevate your Code to Modern C++ with Automated Tooling. Peter Sommerlad

Tokens, Expressions and Control Structures

Exam 3 Chapters 7 & 9

Mechanisms for querying types of expressions: Decltype and auto revisited Programming Language C++ Document no: N1527=

Implementing Abstract Data Types (ADT) using Classes

September 10,

C++ for Java Programmers

Rvalue References as Funny Lvalues

IS0020 Program Design and Software Tools Midterm, Fall, 2004

Ch. 3: The C in C++ - Continued -

An introduction to C++ template programming

Introduction to C++ Systems Programming

Structured bindings with polymorphic lambas

Operator Dot Wording

Overload Resolution. Ansel Sermersheim & Barbara Geller ACCU / C++ June 2018

G52CPP C++ Programming Lecture 13

cast.c /* Program illustrates the use of a cast to coerce a function argument to be of the correct form. */

Upcoming Features in C# Mads Torgersen, MSFT

Chapter 15 - C++ As A "Better C"

CS 162, Lecture 25: Exam II Review. 30 May 2018

Short Notes of CS201

Object-Oriented Programming, Iouliia Skliarova

Sixth lecture; classes, objects, reference operator.

G Programming Languages - Fall 2012

Dialects of ML. CMSC 330: Organization of Programming Languages. Dialects of ML (cont.) Features of ML. Functional Languages. Features of ML (cont.

MARKING KEY The University of British Columbia MARKING KEY Computer Science 260 Midterm #2 Examination 12:30 noon, Thursday, March 15, 2012

POLYMORPHISM 2 PART. Shared Interface. Discussions. Abstract Base Classes. Abstract Base Classes and Pure Virtual Methods EXAMPLE

POLYMORPHISM 2 PART Abstract Classes Static and Dynamic Casting Common Programming Errors

Pointers. 1 Background. 1.1 Variables and Memory. 1.2 Motivating Pointers Massachusetts Institute of Technology

CS201 - Introduction to Programming Glossary By

A Fast Review of C Essentials Part I

Object Oriented Design

CS201- Introduction to Programming Current Quizzes

Operator Dot Wording

(5 2) Introduction to Classes in C++ Instructor - Andrew S. O Fallon CptS 122 (February 7, 2018) Washington State University

C++ Important Questions with Answers

1. The term STL stands for?

Compilers. Type checking. Yannis Smaragdakis, U. Athens (original slides by Sam

Software Engineering Concepts: Invariants Silently Written & Called Functions Simple Class Example

Decltype (revision 5)

04-19 Discussion Notes

Vector and Free Store (Pointers and Memory Allocation)

explicit class and default definitions revision of SC22/WG21/N1582 =

Chapter 1 INTRODUCTION SYS-ED/ COMPUTER EDUCATION TECHNIQUES, INC.

CS11 Advanced C++ Fall Lecture 7

Classes. Logical method to organise data and functions in a same structure. Also known as abstract data type (ADT).

CISC220 Lab 2: Due Wed, Sep 26 at Midnight (110 pts)

COEN244: Class & function templates

What does it mean by information hiding? What are the advantages of it? {5 Marks}

Transcription:

Type Inference C++11 provides mechanisms for type inference which make the compiler deduce the types of expressions. I m starting the book with type inference because it can make your code more concise and expressive. Also, a lot of examples in subsequent chapters rely on these features. auto I m sure everyone has been annoyed at least once by having to type out types like std::map<std::string, std::vector<int>>::iterator. The new keyword auto solves this problem by inferring the type of a variable from the initializing expression: auto i = 5; auto plane = JetPlane("Boeing 737"); plane.model(); for (auto i = plane.engines().begin(); i!= plane.engines().end(); ++i) i->set_power_level(engine::max_power_level); Note: The keyword auto has been in C++ since the beginning, and used to mean this is a local variable. However, that meaning has proven to be of no use and has been removed from the language. Note: According to Bjarne Stroustrup, he had the auto feature working all the way back in 1984, but had to remove it because of C compatibility issues. Those issues went away when C++98 and C99 started requiring every variable and function to be defined with an explicit type. auto isn t merely syntactic sugar, however. In some situations it can be not just inconvenient, but actually di cult or impossible to write C++11 code without auto. For 16

example, when the code in a template depends on the types of the arguments, it can be hard to specify the type explicitly. But the compiler can choose the appropriate types once it knows the types of the arguments: void multiply(const X& x, const Y& y) auto result = x * y; // without auto, it can be hard to specify // the type of result //... You should be aware that variables declared with auto still have a static type just like any other variables, and the compiler needs to have enough information (in the form of an initializing expression) to figure the type out. This is why you can t declare arrays with auto, oruseitforfunctionparametersormembervariables.noneofthefollowingwill compile: void invalid(auto i) class A auto_m; ; int main() auto arr[10]; Using the keyword has a lot of advantages over specifying types explicitly: it reduces verbosity of the code and makes it more DRY it promotes a higher level of abstraction and coding to interfaces it helps future-proof the code as it allows types to change without necessarily requiring code that uses them to change it allows for easier refactoring, e.g. changing class names or function return types 17

it allows template code to be simpler because now you can avoid specifying some of the types for intermediate expressions by using auto it s much easier to declare variables of undocumented types it allows you to store lambdas for later use. I ll talk about lambdas in the next chapter, but the key thing here is that you can t know the type of lambda expressions so you can t declare a variable to assign a lambda expression to without auto. Note: DRY stands for Don t Repeat Yourself. This principle was defined in the book called The Pragmatic Programmer by Dave Thomas and Andy Hunt. It promotes reduced repetition of information. As a rule of thumb, you should always use auto unless you require a type conversion, i.e. the type inferred by auto wouldn t be the type you want. A type conversion may be required, for example, when you get some proxy type from a template and you want it to decay. Acommonobjectiontoauto is that it obscures the type information and makes code hard to comprehend for a new programmer. It is a valid consideration, but the benefits outlined above outweigh it. The fact that the types of variables are less obvious is mitigated to a large degree by IntelliSense and by the improved readability achieved by not having type name duplication all over the code. Consider that similar objections have been made for a long time about other C++ features such as operator overloading, and yet they contribute to more powerful and expressive code. auto is in the same camp. An interesting thing about auto is that the compilers have had the ability to infer types for a long time as they had to figure out the types of template arguments. The mechanism behind auto is the same as that used for templates: template<typename T> void f(t t) f(expr); // T is deduced from expr auto var = expr; // type of var is deduced from expr, same as above auto can be used to declare multiple variables, as long as all the initializing expressions result in the same deduced type: 18

auto a = 5.0, b = 10.0; auto i = 1.0, *ptr = &a, &ref = b; auto j = 10, str = "error"; // regular variable, pointer and // reference declarations // error: initializing // expressions of different types You can add const or volatile qualifiers to your auto declarations, as well as turn them into a pointer, a reference or an rvalue reference (rvalue references will be discussed in a later chapter): map<string, int> index; const auto j = index; auto& ref = index; const auto& cref = index; auto* ptr = &index; If you aren t declaring a reference, some type transformations are applied automatically: the const and volatile specifiers are removed from the initializing type arrays and functions are turned into pointers. For example: const vector<int> values; auto a = values; // type of a is vector<int> auto& b = values; // type of b is const vector<int>& volatile longclock = 0; auto c = clock; // c is not volatile JetPlane fleet[10]; auto e = fleet; auto& f = fleet; auto g = func; auto& h = func; // type of e is JetPlane* // type of f is JetPlane(&)[10] - a reference // type of g is int(*)(double) // type of h is int(&)(double) 19

You can use either assignment or copy initialization syntax to initialize your auto variables, unless the inferred type has an explicit copy constructor: int i = 10; auto a = i; auto b(i); struct Expl Expl() explicit Expl(constExpl&) ; Expl e; auto c = e; // illegal Decltype Another construct that deals with inferring types is the decltype specifier. You pass an expression to it, and it figures out the type of the expression: int i = 10; cout << typeid(decltype(i + 1.0)).name() << endl; // outputs "double" Note that it does not evaluate the expression, so in the example below the value of a won t change outside the context of decltype: decltype(a++) b; decltype is considered to be a type specifier so the intention is for you to be able to use decltype(expr) in place of a type name anywhere: vector<int> a; decltype(a) b; b.push_back(10); decltype(a)::iterator iter = a.end(); 20

It is particularly useful when writing templated functions where the return type depends on the template arguments: auto multiply(x x, Y y) -> decltype(x * y) return x * y; The example above uses the new syntax for declaring functions with a trailing return type. This is discussed in detail below. Because decltype is a type specifier, it ignores const and volatile qualifiers. If you want to get a const reference from decltype, put the expression into parentheses: is_reference<decltype((i))>::value; // evaluates to true Side e ects decltype does not evaluate the expression that s given to it. So, for example, here the value of a won t change outside the context of decltype: auto a = 10; decltype(a++) b; cout << a << endl; // outputs 10 as value of a is unchanged Nonetheless, even though the expression isn t evaluated, decltype can still have a potential side e ect due to template instantiation. Consider this example: template <int I> struct Num static const auto c = I; decltype(i) _member; Num() : _member(c) ; int i; decltype(num<1>::c, i) var = i; // type of var is int& 21

Ipassedanexpressionwiththecommaoperatortodecltype in the last statement of this example. The comma operator returns the last argument, so var will have the same base type as i, but the compiler will still need to instantiate the Num template to make sure the expression is valid. This template instantiation is a side e ect, which you may sometimes prefer not to happen. Trailing return types The keyword auto has a di erent meaning when it s used in conjunction with function declarations. C++11 introduces an alternative syntax for declaring functions, where the return type is specified after the parameters (hence trailing return type). In order to use this syntax, you have to start your function declaration with auto: auto multiply(x x, Y y) -> decltype(x * y) returnx * y; The reason for introducing this syntax is that it allows you to declare templated functions where the return type depends on the type of the arguments. With the old syntax, there was a scoping problem: ReturnType multiply(x x, Y y) returnx * y; IwantReturnType to be the type of (x * y) but I have no way of specifying it, because x and y aren t in scope yet: decltype(x * y) multiply(x x, Y y) // x and y in decltype aren t // in scope yet! return x * y; 22

This is where trailing return types come to the rescue. Putting the return type after the parameter list allows the parameters to be used to specify the return type. Note: There is a hack which allows you to use type names instead of the parameter names, but it s ugly and error-prone: template<class X, class Y> decltype(*(x*)(0) * *(Y*)(0)) mul2(x x, Y y) return x * y; 23