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
的用法,可以提高我们开发的效率和代码质量。