Effective Modern C++ Note

本文记录Effective Modern C++ 笔记

性别推导

  1. param is T&
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
template<typename T>
void f(T& param);  // param is a reference

int x = 27;  // x is an int
const int cx = x;  // cx is a const int
const int& rx = x;  // rx is a reference to x as a const int

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&
  1. param is const T&
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
template<typename T>
void f(const T& param);  // param is now a ref-to-const

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

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&
  1. param is T*
1
2
3
4
5
6
7
8
9
template<typename T>
void f(T* param);  // param is now a pointer

int x = 27;  // as before
const int *px = &x; // px is a ptr to x as a const int

f(&x);  // T is int, param's type is int*
f(px); // T is const int,
        // param's type is const int*
  1. param is T&&

If expr is an lvalue, both T and ParamType are deduced to be lvalue references.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
template<typename T>
void f(T&& param); // param is now a universal reference

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

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&&
  1. param is T

That means that param will be a copy of whatever is passed in—a completely new object.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
template<typename T>
void f(T param);  // param is now passed by value

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

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
  1. Array Arguments
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const char name[] = "J. P. Briggs"; // name's type is
                                    // const char[13]
const char * ptrToName = name;  // array decays to pointer

template<typename T>
void f(T param);  // template with by-value parameter

f(name);  // name is array, but T deduced as const char*

/*********second condition***********/
template<typename T>
void f(T& param);  // template with by-reference parameter
f(name);  // pass array to f, T is const char [31], param is const char (&)[13]


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 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<typename T, std::size_t N>
constexpr std::size_t arraySize(T (&)[N]) noexcept
{
 return N;
}

int keyVals[] = { 1, 3, 7, 9, 11, 22, 35 };
int mappedVals[arraySize(keyVals)];
  1. Function Arguments
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
void someFunc(int, double); // someFunc is a function;
                            // type is void(int, double)
template<typename T>
void f1(T param); // in f1, param passed by value

template<typename T>
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)
  1. 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.
updatedupdated2021-11-062021-11-06