C++中的std::is_convertible模板及示例
在C++中,有很多模板可以方便我们进行类型转换或者类型判断。其中一个非常有用的模板就是std::is_convertible。这个模板可以用来判断某个类型是否可以被隐式转换成另一个类型。本文将为大家介绍std::is_convertible的用法及示例代码。
std::is_convertible的用法
std::is_convertible是一个类型判断模板,定义在<type_traits>头文件中。它的使用非常简单,只需要将两种类型作为模板参数传入即可。第一个参数表示要判断的类型,第二个参数表示需要将其转换的类型。例如,下面就是一个示例:
#include <type_traits>
#include <iostream>
using namespace std;
int main()
{
bool b = is_convertible<int,double>::value;
cout<<b<<endl;
return 0;
}
上面这段代码的意思是判断int是否可以被隐式转换成double,并将结果保存在bool类型的变量b中。运行这个程序,会输出true,也就是可以被转换。
示例一:整型类型转换
下面我们来写一个示例程序,来演示如何使用std::is_convertible进行类型转换判断。
#include <type_traits>
#include <iostream>
using namespace std;
template<typename T>
void processInts(T num)
{
if(is_convertible<T, int>::value)
{
int intValue = static_cast<int>(num);
cout<<"Integer value is "<<intValue<<endl;
}
else
{
cout<<"Not an integer"<<endl;
}
}
int main()
{
processInts(5);
processInts(3.14);
return 0;
}
上面的代码定义了一个模板函数processInts,接收一个参数num,判断这个参数是否可以被转换为整型。如果可以,就输出这个整型值;否则输出提示信息通知用户其不是一个整型。
在main函数中我们分别调用了processInts(5)和processInts(3.14),得到的输出分别是:
Integer value is 5
Not an integer
可以看到,对于整型参数5,processInts函数判断其可以被转换成整型,并成功输出了这个整型值;而对于浮点型参数3.14,则无法被转换成整型,输出了提示信息。
示例二:类类型转换
除了基本数据类型之外,std::is_convertible还可以用于判断类类型之间是否可以进行隐式类型转换。下面我们就用一个类类型转换的示例来演示。
#include <type_traits>
#include <iostream>
using namespace std;
class Animal
{
public:
virtual void eat() = 0;
};
class Dog : public Animal
{
public:
void eat() override
{
cout<<"Dog eating..."<<endl;
}
};
template<typename T>
void processAnimal(T animal)
{
if(is_convertible<T, shared_ptr<Animal>>::value)
{
shared_ptr<Animal> animalPtr = animal;
animalPtr->eat();
}
else
{
cout<<"Unsupported animal type"<<endl;
}
}
int main()
{
processAnimal(make_shared<Dog>());
processAnimal(Animal()); //编译错误,无法进行隐式类型转换
return 0;
}
上面这段代码定义了两个类Animal和Dog,Dog是Animal的子类,并重载了eat方法。
processAnimal函数接收一个参数animal,判断其是否可以被转换成shared_ptr<Animal>类型。如果可以,就将参数转换成这种类型,并调用其eat方法;否则输出一条错误信息。
在main函数中,我们在调用processAnimal时分别传入了一个Dog类型的对象和一个Animal类型的匿名对象。由于Dog是Animal的子类,可以被隐式转换成Animal类型,同时又可以被转换成shared_ptr<Animal>类型,因此第一次调用processAnimal函数成功输出了Dog eating...。而对于第二次调用,编译器会提示无法将Animal类型隐式转换成shared_ptr<Animal>类型。
示例三:函数指针类型转换
std::is_convertible还可以用于判断函数指针类型之间是否可以进行隐式类型转换。下面我们就用一个函数指针类型转换的示例来演示。
#include <type_traits>
#include <iostream>
using namespace std;
void funcA(int a)
{
cout<<"Function A called with "<<a<<endl;
}
void funcB(int a, int b)
{
cout<<"Function B called with "<<a<<" "<<b<<endl;
}
template<typename FuncType>
void processFunction(FuncType func)
{
if(is_convertible<FuncType, void(*)(int)>::value)
{
void(*funcPtr)(int) = func;
funcPtr(10);
}
else if(is_convertible<FuncType, void(*)(int,int)>::value)
{
void(*funcPtr)(int,int) = func;
funcPtr(10,20);
}
else
{
cout<<"Unsupported function type"<<endl;
}
}
int main()
{
processFunction(funcA);
processFunction(funcB);
processFunction([](){cout<<"Lambda expression called"<<endl;}); //编译错误
return 0;
}
上面这段代码定义了两个函数funcA和funcB,分别接收一个和两个int类型的参数,并输出调用信息。
processFunction函数接收一个函数指针类型的参数func,判断其是否可以被转换成接受一个int或者两个int类型参数的函数指针类型。如果可以,就将参数转换成合适的类型,并调用对应的函数;否则输出一条错误信息。
在main函数中,我们分别调用了processFunction(funcA)和processFunction(funcB),分别传入了两个不同的函数指针。可以看到,第一次调用成功输出了Function A called with 10,而第二次则成功输出了Function B called with 10 20。但是对于最后一次传入一个lambda表达式,编译器则会提示无法将lambda表达式类型隐式转换成函数指针类型。
结论
std::is_convertible是一个非常好用的模板,可以方便我们进行类型转换的判断,避免了一些类型错误的发生。在实际开发中,我们经常会面临需要类型转换的情况,掌握了std::is_convertible的用法,可以提高我们开发的效率和代码质量。
极客笔记