探讨侯捷老师关于variadic template讲义的一处表述

最近在学习侯捷老师的c++视频。其中关于variadic template的讲义25:00处的一处讲述似乎不对,特地拿出来与大家探讨。视频源

https://www.youtube.com/watch?v=TJIb9TGfDIw&list=WL&index=4&t=1414shttps://www.youtube.com/watch?v=TJIb9TGfDIw&list=WL&index=4&t=1414s在第25分钟处,侯老师说,当args...有零个参数才会调用第三个hash_val(原话是“只剩一个种子和0个参数”)。似乎不对。应为当args...有1个参数就会调用第三个hash_val。

讲一下我的理解:

1 既然仿函数CustomHash有返回值,所以它调用的hash_val就必须是有返回值的第三个函数。

2 第三个hash_val又会调用如下:

hash_val(seed, args...);

理论上说,这可以是自身的递归调用,但是由于seed是size_t类型,跟第一、第二个函数更匹配,所以应从前两个函数里选一个调用。

第一个函数的第二个参数只能是单个变量,而args...是一包(准确的说,是三个变量)。所以第二个函数更匹配,因此调用第二个函数hash_val

3 第二个函数又一次调用了

hash_val(seed, args...);

此时args...含有两个变量。所以第一个hash_val仍然不合适,还是要调用第二个hash_val

4 第二个函数再一次调用了

hash_val(seed, args...);

此时args...含有1个变量。所以第一个hash_val最合适,应该被调用。

最终的次序是,先调用第一个函数,再调用第二个,然后再调用第二个,最后调用第一个hash_val。

附上代码检验:

#include <functional>
#include <string>
#include <iostream>

template <typename T>
inline void hash_combine(size_t& seed, const T & val)
{
	seed ^= std::hash<T>()(val);
}

template <typename T>
inline void hash_val(size_t & seed, const T & val)
{
	int iIdx = 1;
	printf("%d\n", iIdx);
	hash_combine(seed, val);
}

template <typename T, typename... Types>
inline void hash_val(size_t & seed, const T & val, const Types&... args)
{
	int iIdx = 2;
	printf("%d\n", iIdx);
	hash_combine(seed, val);
	hash_val(seed, args...);

}

template <typename... Types>
inline size_t hash_val(const Types&... args)
{
	int iIdx = 3;
	printf("%d\n", iIdx);
	size_t seed = 0;
	hash_val(seed, args...);
	return seed;
}

class Cus
{
public:
	std::size_t operator()(std::string & str1, std::string & str2, int & i3){
		return hash_val(str1, str2, i3);
	}
};

int main(void)
{
	Cus f;
	int i = 4;
	size_t t = f(std::string("123"), std::string("abc"), i);
	std::cin.get();
	return t;
}

测试结果,与分析一致:

进一步,假如改写第一个hash_val函数,使其输入参数变为3个,则第二个hash_val只会调用一次。因为当args...包含两个参数时,第一个hash_val函数可以认为是一个特化函数,比第二个函数更匹配:

template <typename T1, typename T2>
inline void hash_val(size_t & seed, const T1 & val1, const T2 & val2)
{
	int iIdx = 1;
	printf("%d\n", iIdx);
	hash_combine(seed, val1);
	hash_combine(seed, val2);
}

检验:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值