template<typename T>
void f(ParamType param);
// 假设调用语句如下
f(expr);
T 的类型是由 ParamType 的形式和expr的类型共同决定的.
以下分三类情况讨论:
在这种情况下, 类别推导会这样运作:
template<typename T>
void f(T& param);
int x = 27;
const int cx = x;
const int& rx = x;
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&
参数为常量引用时也如此,先忽略调const和引用,再根据expr的类型和ParamType来推导T
template<typename T>
void f(const T& param);
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&
万能引用是指这样的引用:(万能引用将在条款24中详细讨论)
template<typename T>
void f(T&& param);
万能引用的类型推导规则:
template<typename T>
void f(T&& param);
int x = 27;
const int cx = x;
const int& rx = x;
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一样
// 如果expr是一个右值, ParamType都会被推导为右值引用
f(27); // T is int, param's type is int&&
推导规则:
template<typename T>
void f(T param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); // T is int, param's type is also int
f(cx); // T is int, param's type is also int
f(rx); // T is int, param's type is also int
底层const含义: 一个指针指向的对象是const, 但是指针本身不是const
顶层const含义: 一个指针本身是const, 但是指针指向的对象不是const
template<typename T>
void f(T param);
const char* const ptr = "Fun with pointers"; // ptr is a const pointer to const char
f(ptr); // T is const char*, param's type is const char*
// 顶层const被忽略, 底层const保留
template<typename T>
void f(T param);
char name[] = "J. P. Briggs";
f(name); // T is char*, param's type is char*
但是实际上数组型别和指针并不完全相同,数组型别包含有对应的数组大小的信息,如果我们希望参数仍然是一个数组型别而不是指针,可以使用引用传值
template<typename T>
void f(T& param);
char name[] = "J. P. Briggs";
f(name); // T is char[13], param's type is char (&) [13]
很有意思的我们可以利用这个数组引用这个特性创造出一个模板,可以在编译期就知道传入的数组的大小
template<typename T, std::size_t N>
constexpr std::size_t arraySize(T (&)[N]) noexcept {
return N;
}
template<typename T>
void f1(T param);
template<typename T>
void f2(T& param);
void someFunc(int, double);
f1(someFunc); //param's type is void(*)(int, double)
f2(someFunc); //param's type is void(&)(int, double)
总结:
参考资料:《Modern Effective C++》第五版