Declarations

C++11 implements several features that simplify declarations, particularly for situations arising when templates are used.

auto

C++11 strips the keyword auto of its former meaning as a storage class specifier (Chapter 9, “Memory Models and Namespaces”) and puts it to use (Chapter 3) to implement automatic type deduction, provided that an explicit initializer is given. The compiler sets the type of the variable to the type of the initialization value:

auto maton = 112;  // maton is type int
auto pt = &maton;  // pt is type int *
double fm(double, int);
auto pf = fm;      // pf is type double (*)(double,int)

The auto keyword can simplify template declarations too. For example, if il is an object of type std::initializer_list<double>, you can replace

for (std::initializer_list<double>::iterator p = il.begin();
                                             p !=il.end(); p++)

with this:

for (auto p = il.begin(); p !=il.end(); p++)

decltype

The decltype keyword creates a variable of the type indicated by an expression. The following statement means “make y the same type as x,” where x is an expression:

decltype(x) y;

Here are a couple of examples:

double x;
int n;
decltype(x*n) q; // q same type as x*n, i.e., double
decltype(&x) pd; // pd same as &x, i.e., double *

This is particularly useful in template definitions, when the type may not be determined until a specific instantiation is made:

template<typename T, typename U)
void ef(T t, U u)
{
    decltype(T*U) tu;
    ...
}

Here, tu is of whatever type results from the operation T*U, assuming that operation is defined. For example, if T is char and U is short, tu would be of type int because of the automatic integer promotions that take place in integer arithmetic.

The workings of decltype are more complicated than those of auto, and the resulting types can be references and can be const-qualified, depending on the expressions used. Here are some more examples:

int j = 3;
int &k = j
const int &n = j;
decltype(n) i1;      // i1 type const int &
decltype(j) i2;      // i2 type int
decltype((j)) i3;    // i3 type int &
decltype(k + 1) i4;  // i4 type int

See Chapter 8, “Adventures in Functions,” for the rules that lead to these results.

Trailing Return Type

C++11 introduces a new syntax for declaring functions, one in which the return type comes after the function name and parameter list instead of before them:

double f1(double, int);          // traditional syntax
auto f2(double, int) -> double;  // new syntax, return type is double

The new syntax may look like a step backwards in readability for the usual function declarations, but it does make it possible to use decltype to specify template function return types:

template<typename T, typename U)
auto eff(T t, U u) -> decltype(T*U)
{
    ...
}

The problem that’s addressed here is that T and U are not in scope before the compiler reads the eff parameter list, so any use of decltype has to come after the parameter list. The new syntax makes that possible.

Template Aliases: using =

It’s handy to be able to create aliases for long or complex type identifiers. C++ already had typedef for that purpose:

typedef std::vector<std::string>::iterator itType;

C++11 provides a second syntax (discussed in Chapter 14, “Reusing Code in C++”) for creating aliases:

using itType = std::vector<std::string>::iterator;

The difference is that the new syntax also can be used for partial template specializations, whereas typedef can’t:

template<typename T>
  using arr12 = std::array<T,12>;  // template for multiple aliases

This statement specializes the array<T,int> template by setting the int parameter to 12. For instance, consider these declarations:

std::array<double, 12> a1;
std::array<std::string, 12> a2;

They can be replaced with the following:

arr12<double> a1;
arr12(std::string> a2;

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.27.251