条款3:理解decltype

博客探讨了C++11和C++14中decltype的作用,特别是在声明返回类型依赖于参数类型的函数模板时的应用。文中举例说明了decltype如何获取表达式的类型,并解释了在C++14中如何使用auto和decltype(auto)进行类型推导,以及在函数返回值类型推导时可能遇到的问题和解决方案。
摘要由CSDN通过智能技术生成

对于给定的名字或表达式,decltype能告诉你改名字或表达式的类型;考虑如下代码:

const int i = 0; //decltype(i)是const int

bool f(const Widget &w); // decltype(w)是const Widget &
						 // decltype(f)是bool f(const Widget&)

struct Point {			// decltype(Point::x)是int
	int x,y;			
};

Widget W;               // decltype(w)是Widget

if (f(w)) ...			// decltype(f(w))是bool

vector<int> v;			// decltype(v)是vector<int>

if (v[0] == 0) ...		// decltype(v[0])是int&

C++11中,decltype的主要用途大概就在于声明那些返回值类型以来与形参类型的函数模板;如:

template<typename Container, typename Index>
auto authAndAccess(Container &c, Index i)
  -> decltype(c[i])
 {
 	authenticateUser();
 	return c[i]; 	
 }

采用这么一个声明后,operator[]返回值是什么类型,authAndAccess的返回值就是什么类型,和我们期望的结果一致;
而在C++14中可以去掉返回值类型尾序语法:

template<typename Container, typename Index> // C++14
auto authAndAccess(Container &c, Index i)    // 不一定正确
{
 	authenticateUser();
 	return c[i]; 	
}

条款2说过:编译器会对auto指定为返回类型的函数实现模板类型推导:

std::deque<int> d;
// ...
authAndAccess(d, 5) = 10;

上述代码中d[5]返回的是int&,但是对于authAndAccess的返回值实施auto类型推导将剥去引用饰词,这么一来返回值类型就成了int,将10赋值给一个右值int显然是错误的;
想要authAndAccess正确运行,就要对返回值实施decltype类型推导,在C++14中通过decltype(auto)饰词解决了这个问题:

template<typename Container, typename Index> // C++14能够运作,但仍亟须改进
decltype(auto)
authAndAccess(Container& c, Index i)
{
	authenticateUser();
	return c[i];
}

现在一般情况下c[i]返回T&authAndAccess也会返回T&,若你也想在初始爱护表达式处应用decltype类型推导规则,也可以照样操作:

Widget w;
const Widget& cw = w;
auto myWidget1 = cw; 			// auto类型推导:myWidget1的类型是Widget
decltype(auto) myWidget2 = cw;	// decltype类型推导,myWidget2的类型是cosnt Widget&
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
辅助函数(3)的作用是选择一个中心点(也就是 pivot)来分割序列,以便进行快速排序等算法。函数模板的定义如下: ```cpp template <typename Iterator, typename CMP_T=std::less<decltype(*Iterator())>> Iterator choosepivot(Iterator left, Iterator right, CMP_T cmp=CMP_T()); ``` 其中,`left` 和 `right` 分别表示序列的左右两个边界,`cmp` 是一个可调用对象,用于比较两个元素的大小。函数返回值是一个迭代器,指向选择出来的中心点。 以下是一个示例实现: ```cpp template <typename Iterator, typename CMP_T> Iterator choosepivot(Iterator left, Iterator right, CMP_T cmp) { Iterator mid = left + (right - left) / 2; // 取中间位置 if (cmp(*mid, *left)) // 保证 left <= mid std::swap(left, mid); if (cmp(*right, *left)) // 保证 left <= right std::swap(left, right); if (cmp(*mid, *right)) // 保证 mid >= right std::swap(mid, right); return mid; } ``` 辅助函数(4)的作用是将序列分为两部分,一部分比中心点小,一部分比中心点大,以便进行快速排序等算法。函数模板的定义如下: ```cpp template <typename Iterator, typename CMP_T=std::less<decltype(*Iterator())>> void partition(Iterator left, Iterator right, CMP_T cmp=CMP_T()); ``` 其中,`left` 和 `right` 分别表示序列的左右两个边界,`cmp` 是一个可调用对象,用于比较两个元素的大小。函数不返回值,但会将序列分成两部分。 以下是一个示例实现: ```cpp template <typename Iterator, typename CMP_T> void partition(Iterator left, Iterator right, CMP_T cmp) { Iterator pivot = choosepivot(left, right, cmp); // 选择中心点 std::swap(*pivot, *(right - 1)); // 将中心点放到末尾 pivot = right - 1; Iterator i = left - 1; for (Iterator j = left; j != pivot; ++j) { if (cmp(*j, *pivot)) { // 如果 j 所指元素小于中心点 ++i; std::swap(*i, *j); // 将 j 所指元素和 i 所指元素交换 } } ++i; std::swap(*i, *pivot); // 将中心点放回到正确的位置 partition(left, i, cmp); // 递归处理左半部分 partition(i + 1, right, cmp); // 递归处理右半部分 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值