using和typedef的区别及C++函数什么时候显示初始模板?

这几天在读effective modern C++,为什么有些函数需要显示的模板初始化,众所周知,定义或者声明一个类对象的时候才需要显示的模板初始化,那为什么有些函数需要显示模板初始化?

直接搜索为什么显示初始模板,搜不到,查了查资料,了解了如果这个模板参数不涉及到推导,那么就必须要显示的初始化,如

template<typename T>
void fcn(){//T不涉及到推导,所以必须显示初始化
}
template<typename T1,typename T2>
void fcn(T2 lhs){//T1也不涉及类型推导,需要显示的初始化
}

又比如函数的形参是一个类型别名,这个类型别名还是用struct包装的
如下:

template<typename T>
void fcn18(typename std::remove_reference<T>::type lhs) {
	cout << "hello" << endl;
}

template<typename T>
void fcn19(std::remove_reference_t <T>lhs) {
	cout << "hello" << endl;
}
int main(){
	int a = 2;
	int& b = a;
	fcn18<int>(b);
	fcn19<int>(a);
	return 0;
}

typename std::remove_reference::type是C++98年的类型别名,代码十分的长,需要加typename告诉编译器type指向是一个类型不是数据成员。 C++98年的类型别名不支持模板,所以只能用一个struct来进行包装,变成模板类型别名。
remove_reference_t使用的是C++11新增的别名,采用using来别名声明,支持模板,VS里的remove_reference_t源码如下

template <class _Ty>
using remove_reference_t = typename remove_reference<_Ty>::type;

回到咱们的问题来,为什么fcn18和fcn19还是需要显示模板初始化,remove_reference使用了struct(struct和class除了默认的访问权限其他什么区别都没有)就像一个类的对象必须显示声明模板一样,所以也要给该函数显示声明类型,remove_reference_t也只不过是包装了一下remove_reference,所以照旧需要显示模板初始化。

这个问题也是我在看完美转发里的std::forward想到的,因为我看调用forward函数就必须显示初始化模板,forward函数的形参和我所说的第二种情况是一样的,以下是std::forward的源码

template <class _Ty>
_NODISCARD constexpr _Ty&& forward(
    remove_reference_t<_Ty>& _Arg) noexcept { // forward an lvalue as either an lvalue or an rvalue
    return static_cast<_Ty&&>(_Arg);
}

template <class _Ty>
_NODISCARD constexpr _Ty&& forward(remove_reference_t<_Ty>&& _Arg) noexcept { // forward an rvalue as an rvalue
    static_assert(!is_lvalue_reference_v<_Ty>, "bad forward call");
    return static_cast<_Ty&&>(_Arg);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值