> 文章列表 > 现代C++技术研究(2)---模板类型推导(2)

现代C++技术研究(2)---模板类型推导(2)

现代C++技术研究(2)---模板类型推导(2)

第二种情况:ParamType是一个通用引用(Universal Reference)

这种情况,模板类型推导的结果,就不那么直观了。看如下测试用例:

#include <iostream>
#include <type_traits>template<typename T> void f(T&& param)
{using ParamType = T&&;bool TIsInt = std::is_same<T, int>::value;bool TIsConstInt = std::is_same<T, const int>::value;bool TIsIntRef = std::is_same<T, int&>::value;bool TIsConstIntRef = std::is_same<T, const int&>::value;if (TIsInt) {std::cout << "T is int, ";} else if (TIsConstInt) {std::cout << "T is const int, ";} else if (TIsIntRef) {std::cout << "T is int&, ";} else if (TIsConstIntRef) {std::cout << "T is const int&, ";} bool ParamTypeIsIntRef = std::is_same<ParamType, int&>::value;bool ParamTypeIsConstIntRef = std::is_same<ParamType, const int&>::value;bool ParamTypeIsIntRefRef = std::is_same<ParamType, int&&>::value;if (ParamTypeIsIntRef) {std::cout << "param's type is int&\\n";} else if (ParamTypeIsConstIntRef) {std::cout << "param's type is const int&\\n";} else if (ParamTypeIsIntRefRef) {std::cout << "param's type is int&&\\n";}
}int main()
{int x = 27; // x is an intconst int cx = x; // cx is a const intconst int& rx = x; // rx is a reference to x as a const intf(x);  // x is lvalue, so T is int&, param's type is int&f(cx); // cx is lvalue, so T is const int&, param's type is const int&f(rx); // rx is lvalue, so T is const int&, param's type is const int&f(27); // 27 is rvalue, so T is int, param's type is int&&return 0;
}

可以看到,对于左值,T和ParamType类型相同,对于右值,T去引用,而ParamType是右值引用。

第三种情况:ParamType既不是指针也不是引用

1)传入的参数是引用情况:

#include <iostream>
#include <type_traits>template<typename T> void f(T param)
{using ParamType = T;bool TIsInt = std::is_same<T, int>::value;bool TIsConstInt = std::is_same<T, const int>::value;if (TIsInt) {std::cout << "T is int, ";} else if (TIsConstInt) {std::cout << "T is const int, ";}bool ParamTypeIsInt = std::is_same<ParamType, int>::value;bool ParamTypeIsConstInt = std::is_same<ParamType, const int>::value;if (ParamTypeIsInt) {std::cout << "param's type is int\\n";} else if (ParamTypeIsConstInt) {std::cout << "param's type is const int\\n";}
}int main()
{int x = 27; // x is an intconst int cx = x; // cx is a const intconst int& rx = x; // rx is a reference to x as a const intf(x); // T is int, param's type is intf(cx); // T is int, param's type is intf(rx); // T is int, param's type is intreturn 0;
}

可以看到,推导出的类型,T和ParamType是相同的,并且const和引用都被去掉了。

2)传入的参数是指针的情况:

#include <iostream>
#include <type_traits>using PtrType = const char* const;template<typename T> void f(T param)
{using ParamType = T;bool TIsCstCharPoint = std::is_same<T, const char*>::value;bool TIsCstCharPointCst = std::is_same<T, const int* const>::value;if (TIsCstCharPoint) {std::cout << "T is const char*, ";} else if (TIsCstCharPointCst) {std::cout << "T is const char* const, ";}bool ParamTypeIsCstCharPoint = std::is_same<ParamType, const char*>::value;bool ParamTypeIsCstCharPointCst = std::is_same<ParamType, const int* const>::value;if (ParamTypeIsCstCharPoint) {std::cout << "param's type is const char*\\n";} else if (ParamTypeIsCstCharPointCst) {std::cout << "param's type is const char* const\\n";}
}int main()
{const char* const ptr = "Fun with pointers"; // ptr is const pointer to const objectf(ptr); // T is const char*, param's type is const char*return 0;
}

可以看到,推导出的类型,T和ParamType是相同的,并且后面的const被去掉了,注意,前面的const属性是不能去掉的。

小结:

1)当ParamType是一个通用引用时,传入左值参数,模板的类型推导ParamType结果是左值引用,且ParamType和T相同,传入右值参数,模板的类型推导ParamType结果是右值引用,但ParamType和T是不同的,T去掉引用。

2)当模板参数是值传递时,const和volatile等修饰都会被去掉,且ParamType和T相同。

参考资料:

《Effective Mordern C++》