函数模板限定数据类型 和 类模板限定数据类型 的方法

本文介绍如何在C++中限制函数模板和类模板处理特定数据类型的方法。通过使用`std::enable_if`和自定义类型检查结构体实现对glm库中的`dvec2`和`dvec3`类型的特化处理,并利用`static_assert`确保类模板只适用于int和float类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数模板非常有用,特别实在对不同类型的数据进行统一处理的时候,比如说比较两个数的大小,

template<typename T>
bool compara(T& a,T& b)
{
    return a<b;
}

但是有时候有特殊需求,比如说之前我做的一个项目,需要能够处理以glm中vec2,和vec3为数据类型的数据,进行同样的操作,但是又不能让其他类型的数据能够访问到该函数模板。此时就需要一种限定数据类型(指定模板处理那几个数据类型)的方法。这里有两种方法可以解决函数模板数据类型限定。

第一种

template<typename T>
typename std::enable_if < std::is_same<glm::dvec3, T>::value 
                         || std::is_same<glm::dvec2, T>::value, void >::type
fun(vector<T>& id)
{
    cout << "--" << id[1][0] << endl;
    cout << "--" << id[1][1] << endl;
    cout << "--" << id[1][2] << endl;
}

第二种

template <typename T> struct Checker;
template <> struct Checker<glm::dvec3> { typedef glm::dvec3 Type; };
template <> struct Checker<glm::dvec2> { typedef glm::dvec2 Type; };

template <typename T>
typename Checker<T>::Type
test1(vector<T>& var)
{
    cout << "--" << var[1][0] << endl;
    cout << "--" << var[1][1] << endl;
    return var[1];
}

上面的两种方法,都是当T为dvec3和dvec2时候,程序才能正常编译。

此种方法就可以实现限定访问模板函数的数据类型。

此外,如果是类模板呢?类模板如何限定数据类型?
如果想实现这个功能,那么需用到静态assert。
静态assert可以解决模板的状态检测,使用新的关键字static_assert。
声明采取一下的形式:

static_assert(constant-expression, error-message);

这里有一些使用static_assert的例子:

static_assert(3.14 < GREEKPI && GREEKPI <3.15, "GREEKPI is inaccuratel");
template<class T>
struct Check
{
    static_assert(sizeof(int)<= sizeof(T), "T is not big enough!");
}

当常数表达式为false时,编译器就会产生响应的错误新型。第一个例子是预处理器指令#error的替代方案,第二个例子会在每个模板类别Check生成时检查assertion。

静态assertion在模板之外也是相当有用的。例如,某个算法的实现依赖long long类别的大小比int 还大,这是标准不保证的,这种假设在大多数的系统以及编译器上是有效的,但不是全部。

这里给出一个我测试的例子,帮助大家理解

#include <vector>
#include <iostream>

//定义一个模板类,但是模板类只能处理int 和 float 类型的数据,否则编译不通过
//将会报T type is not the specified DataType including int and float错误提示
template <typename T>
class  Box
{
    static_assert( sizeof(int) == sizeof(T) || sizeof(float) == sizeof(T),
                   "T type is not the specified DataType including int and float");

public:
     Box();
    ~ Box();

    void comprr(T& arr);;

private:
    T aa;
};

template <typename T>
void Box<T>::comprr(T& arr)
{
    std::cout << "******" << arr << std::endl;
}

template <typename T>
Box<T>::~Box()
{}

template <typename T>
Box<T>::Box()
{}

int main() 
{
    int aa = 5;
    float ab = 4.5;
    double ac = 4.4;

    //编译可以通过,类模板使用int数据类型,允许
    Box<int>* box = new Box<int>();
    box->comprr(aa);

    //编译可以通过,类模板使用float数据类型,允许
    Box<float>* box = new Box<float>();
    box->comprr(ab);

    //编译不通过,报错,因为类模板不允许使用double类型
    //Box<double>* box = new Box<double>();
    //box->comprr(ac);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值