C++模板中泛型模板所起到的作用,替换和匹配方式:偏特化的参数看起来比泛化版本要多:以is_pair为例

类似:

fmt里判断是否为reference_wrapper-CSDN博客

fmt.v8::is_contiguous-CSDN博客

现代C++之SFINAE应用(小工具编写)-腾讯云开发者社区-腾讯云

公众号guangcity

问题

第一个my_is_pair和第二个是什么关系,第一个的类型列表里只有一个参数:template<typename T>

。第二个只有两个:template<typename T, typename U>。第二个是偏特化?都偏特化了,类型参数的个数比泛化的还多?


template<typename T>
struct my_is_pair : std::false_type 
{
};

template<typename T, typename U>
struct my_is_pair<std::pair<T, U>> : std::true_type 
{
};

template<typename T>
void fun_pair(T a, std::enable_if_t<my_is_pair<T>::value>* = 0)
{

}


std::pair<double, double> pairdata;
fun_pair(pairdata);

另一个版本

由于在这个例子里,false版本没有用到。所以my_is_pair的泛化版本没有实体,也是可以的:

template<typename T>
struct my_is_pair;

template<typename T, typename U>
struct my_is_pair<std::pair<T, U>> : std::true_type 
{
};

template<typename T>
void fun_pair(T a, std::enable_if_t<my_is_pair<T>::value>* = 0)
{
    double m = 1;
    std::cout << std::endl;
}


std::pair<double, double> pairdata;
fun_pair(pairdata);

泛化版本类型列表里类型的个数和偏特化一样时,反而提示my_is_pair的模板参数太少

但是my_is_pair列表里添加了一个类型,却编不过,提示my_is_pair的模板参数太少。

template<typename T, typename U>
struct my_is_pair;

template<typename T, typename U>
struct my_is_pair<std::pair<T, U>> : std::true_type
{

};

template<typename T>
void fun_pair(T a, std::enable_if_t<my_is_pair<T>::value>* = 0)
{

}


std::pair<double, double> pairdata;
fun_pair(pairdata);

说明:考虑到第一个my_is_pair只有一个typename T,那么第二个my_is_pair(my_is_pair<std::pair<T, U>>)里面的std::pair<T, U>算是一个参数。

如果第一个改成:

template<typename T, typename U>
struct my_is_pair;

那么第二个my_is_pair里面必须也得有第二个类型,比如这样就能编译成功:

template<typename T, typename U>
struct my_is_pair : std::false_type
{
};

template<typename T, typename U>
struct my_is_pair<std::pair<T, U>,U> : std::true_type
{
    using first = T;
    using second = U;
};

//T:std::pair<double, double>

template<typename T>
void fun_pair(T a, std::enable_if_t<my_is_pair<T,double>::value>* = 0)
{
    typename my_is_pair<T,double>::first x{};
    typename my_is_pair<T,double>::second y{};

    std::cout << x << std::endl;
    std::cout << y << std::endl;
    std::cout << 1 << std::endl;
}

std::pair<double, double> pairdata;
fun_pair(pairdata);

或者这样也可以:

学到了。确实是这样。


template<typename T, typename U>
struct my_is_pair : std::false_type
{
};

template<typename T, typename U>
struct my_is_pair<std::pair<T, U>,U> : std::true_type
{
    using first = T;
    using second = U;
};

//T:std::pair<double, double>

template<typename T>
void fun_pair(T a, std::enable_if_t<my_is_pair<T,typename T::second_type>::value>* = 0)
{
    typename my_is_pair<T,T::second_type>::first x{};
    typename my_is_pair<T,T::second_type>::second y{};

    std::cout << x << std::endl;
    std::cout << y << std::endl;
    std::cout << 1 << std::endl;
}


std::pair<double, std::string> pairdata;
fun_pair(pairdata);

分析

果然,编译器先对泛型版本进行处理,

比如用std::pair<double,std::string> 进行推导,先找到泛化版本。

template<typename T>
struct my_is_pair : std::false_type 
{
};

此时T被推导为std::pair<double,std::string>,可以理解为:my_is_pair<T>变成my_is_pair<std::pair<double,std::string>>,这个时候,pair里的first和second的类型是随着整个pair去匹配泛化版本的T的。

然后接着匹配,发现了更合适的偏特化版本(结构):my_is_pair<std::pair<*,*>>

template<typename T, typename U>
struct my_is_pair<std::pair<T, U>> : std::true_type 
{
};

往上一套(推导),这时T->double,  T->std::string。

所以,得看推导的过程。编译器不去比较谁的类型参数更多。

这就是为什么泛化版本的类型列表里的个数,比偏特化的少,最后还能匹配上,这是由编译器处理的顺序决定的。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值