引言
通过实现一个c++小demo,来记录模板编程与c++新特性的学习
需求场景
在客户端进行数据类型输出时,如果某个char类型(比如uint_8)当成int类型使用时,使用std::cout输出可能会达不到想要的结果。
uint8_t int_a = 1;
char ch_a = '1';
std::cout << "int_a :" << int_a << std::endl;
std::cout << "ch_a :" << ch_a << std::endl;
上述代码的输出结果只有ch_a可以正常输出,int_a是无法正常输出的。
因为1对应的ascii码是不可见字符。
正文
enable_if通过定义可以看出,其主要作用是当某个condition成立时,enable_if可以提供某种类型
template <bool, typename T=void>
struct enable_if {
};
template <typename T>
struct enable_if<true, T> {
using type = T;
};
由上可知,只有当第一个参数为ture时,type才有定义;否则使用enable_if::type便会产生编译错误。
但是c++有一个新特性SFINAE:Substitution failure is not an error,即匹配失败不是错误。这句话怎么理解呢?就是当调用模板函数时编译器会根据传入的参数推导最合适的模板函数,在这个推导过程中如果某一个或者几个函数模板推导出来是无法编译通过的,只要有一个可以正确推导出来,那么那几个推导出来可能产生编译错误的模板函数并不会引发编译错误。
简而言之就是:函数模板的匹配过程中,只要有一个匹配成功,其他匹配失败的不会报错。
demo代码:
//util.h
#pragma once
#include<iostream>
template <typename T>
constexpr bool is_char_v = std::_Is_any_of_v<std::remove_cv_t<T>, char, unsigned char, signed char>;
template<typename T>
typename std::enable_if<!is_char_v<T>>::type
PrintValue(const std::string& name, const T& value)
{
std::cout << "!char : " << name << " : " << value << " " << std::endl;
}
template<typename T>
typename std::enable_if<is_char_v<T>>::type
PrintValue(const std::string& name, const T& value)
{
std::cout << "char : " << name << " : " << static_cast<int>(value) << " " << std::endl;
}
//main.cpp
#include "util.h"
int main()
{
uint8_t int_a = 1;
int int_b = 2;
std::cout << "int_a:" << int_a << std::endl;
std::cout << "ch_a:" << int_b << std::endl;
std::cout << "-------------------------------------" << std::endl;
PrintValue("int_a", int_a);
PrintValue("int_b", int_b);
system("pause");
return 0;
}
上述代码的输出结果为: