C++ 模板函数返回值"重载"

1 篇文章 0 订阅
1 篇文章 0 订阅

不想看梳理过程的看这里

传送门

1 简析(真实应用在3.1,不想看那些梳理的直接跳过去)

1.1 问题产生原因

在正常C++语言应用中,函数重载需要保证重载函数的返回值不变,改变函数的入参参数列表,而模板函数通常可以更加完美地实现更灵活的入参参数定义,达到泛型编程的目的,正常情况下,由于模板函数是在编译时未进入函数时进行的函数推导,推导在函数内条件判断之前,因此如果在正常函数内进行的条件判断来确定返回值时,会产生编译错误,由模板函数推导后的函数只能return一种返回值类型,从而导致模板函数难以进行类似重载的操作。

1.2 突破口 C++11特性

C++ 11 可以利用SFINAE根据类型特征有条件地从重载决策中删除函数。

2 解决利器

2.1 SFINAE

SFINAE在CppReference上的链接

SFINAE全称是"Substitution Failure Is Not An Error",即“替换失败不是错误”

在函数模板的重载决议中应用此规则:当将模板形参替换为显式指定的类型或推导的类型失败时,从重载集中丢弃这个特化,而非导致编译失败。
此特性被用于模板元编程。

2.2 std::enable_if

2.2.1 头文件
#include <type_traits>
2.2.2 原理

此元函数是活用 SFINAE ,基于类型特性条件性地从重载决议移除函数,并对不同类型特性提供分离的函数重载与特化的便利方法。
std::enable_if 可用作额外的函数参数(不可应用于运算符重载)、返回类型(不可应用于构造函数与析构函数),或类模板或函数模板形参。

2.2.3 范例

引用自CppReference
错误方法

struct T {
    enum { int_t,float_t } m_type;
    template <typename Integer,
              typename = std::enable_if_t<std::is_integral_v<Integer>>
    >
    T(Integer) : m_type(int_t) {}
 
    template <typename Floating,
              typename = std::enable_if_t<std::is_floating_point_v<Floating>e>
    >
    T(Floating) : m_type(float_t) {} // error: cannot overload
};

正确方法

struct T {
    enum { int_t,float_t } m_type;
    template <typename Integer,
              std::enable_if_t<std::is_integral_v<Integer>, int> = 0
    >
    T(Integer) : m_type(int_t) {}
 
    template <typename Floating,
              std::enable_if_t<std::is_floating_point_v<Floating>, int> = 0
    >
    T(Floating) : m_type(float_t) {} // OK
};
2.2.4 用法解析
auto typeName = std::enable_if<[bool],[typename]>::type
  • 在bool条件为true的情况下,typeName 为 typename类型名
  • 在bool条件为false的情况下,typeName不存在

2.3 std::is_same

2.3.1 头文件
#include <type_traits>
2.3.2 范例

不引用了,心累

2.3.3 用法解析
auto is_same_v = is_same<[type1], [type2]>::value
  • type1类型与type2类型相同时返回is_same_v为true
  • type1类型与type2类型不同时返回is_same_v为false

3 解决方案(不想看梳理过程的直接看这节)

3.1 关键代码部分

  1. 模板定义
#include <type_traits>
#include <string>
template <class T> 
typename std::enable_if<std::is_same<T,std::string>::value,T>::type foo()
{
	return "This is std::string";
}
template <class T> 
typename std::enable_if<std::is_same<T, int>::value, T>::type foo()
{
	return 1;
}
  1. 应用
std::string retString = foo<std::string>();
int retInteger = foo<int>();
  1. 结果
retString = "This is std::string";
retInteger = 1;

4 写在最后

平时不怎么爱写Blog,基本就是在写代码,虽然写的很烂;下半年考研,估计要丢下一阵子代码去复习了,突然感觉很惶恐,最近全天不休的写代码,希望能够有所收获。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值