C++模板编程之: 函数重载与函数特例

/*
C++标准中分辨重载的三个重要准则。
准则一:两候选函数中如果有一方的形参列表与调用实参更匹配,则淘汰另一方。
参数类型匹配规则一般考虑是:匹配度从高到低依此是,同等类型转换,标准类型转换,自定义类型转换
同等类型转换 eg:  char[]<=>char* , 实参char* 转换至const char*
标准类型转换: int => long
自定义类型转换: int=> 用户自定义类型A,且A有构造函数A(int)   此类型转换需要找到更多资料来阅读

#1  
void func(char*a,long b,long c,long d);
#2
void func(char a[],long b,int c,long d);
#3
void func(char a[],long b,long c,int d);

void call (char a[],int b,int c,int d)
{
    func(a,b,c,d);
}

对于这个例子,看看这三个谁的匹配度更高
#1的参数1是同等类型转换,其它三个都是标准类型转换
#2的参数1和参数3是同等类型转换,其它两个是标准类型转换
#3的参数1和参数4是同等类型转换,其它两个是标准类型转换
候选是#2和#3,由于无法确定2和3谁的匹配度更高,编译器将报错


准则二:两函数如果形参列表类型同等匹配实参列表类型时,取非函数模板而淘汰函数模板特例

准则三:两函数如果形参列表类型同等匹配实参列表类型时,若两者都是函数模板实例,则取更特殊的那一个。
特殊的规则:如果所有能匹配A的模板参数也能匹配B,但匹配B的模板参数不能匹配A,则A是更特殊的那个。
换言之,A是B的真子集,此时A是更特殊的。

考虑下面的例子:
template<typename T0,typename T1,typename T2>
struct S
{
    std::string id() {return "General" ;}
}

#1 约束第三参数必须为char
template<typename T0,typename T1>
struct S<TO,T1,char>
{
    std::string id() {return "Specialization #1" ;}
}

#2 约束第二、第三参数必须为char
template<typename T0>
struct S<T0,char,char>
{
     std::string id() {return "Specialization #2" ;}
}

#3 约束第一参数必须为int,且第二、第三参数相同
template<typename T>
struct S<int,T,T>
{
    std::string id() {return "Specialization #3" ;}
}

call:
    //匹配#1
    cout<<S<float,float,float>().id()<<endl; 

    //  只与#3匹配,选#3
    cout<<S<int,int,int>().id()<<endl;  

    //与#1和#2匹配,但#2更特殊
    cout<<S<char,char,char>.id()<<endl; 

    //#2和#3似乎都能匹配,但这两个模板特例互不为真子集概念,因此此调用有歧义。
    //因为Schar,char,char>匹配#2不匹配#3,而S<int,float,float>匹配#3不匹配#2
    //此例即说明,模板特例允许存在歧义,但调用会导致歧义,编译出错。
    cout<<S<int,char,char>().id()<<endl; 
*/
#include "stdafx.h"
#include<iostream>
// #1  函数模板
template<typename T>
void func(T v) { std::cout << "#1" << '\n'; }

// #2  函数模板特化
template<>
void func(float v) { std::cout << "#2" << '\n'; }

// #3  函数重载
void func(float v) { std::cout << "#3" << '\n'; }

// #4  不相关项
void func2(float v) { std::cout << "#4" << '\n'; }
int _tmain(int argc, _TCHAR* argv[])
{
    func2(1); //与#4匹配
    func(1);  //与#1匹配
    func(1.); //实参明确为double,更匹配#1
    func(1.f); //实参明确为float,更匹配#3
    func<>(1.f); //明确表明这是一个模板特化版本实例调用,匹配#2
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值