C++基础——使用字符串作为函数模板的实参

<C++基础——一些细节、常犯错误的汇总>一文的细节3中,我们看到,

const char* s = "hello";

s的类型是const char*"hello"的类型是const char[6]是数组类型,也就是与"hell"(const char[5])具有不同的数据类型。

这一点在函数模板(以字符串为参数)的设计中,显得尤为重要。

template<typename T>
inline const T& max(const T& x, const T& y)
{
    return x > y ? x : y;
}

int main(int, char**)
{
    ::max("hello", "world");    // 正确,具有相同的实参类型,const char[6],
                                // 这样在类型推导时都能匹配到同一个类型
    ::max("hello", "hell");     // 错误, 不同类型的实参
    std::string s("world");
    ::max("hello", s);          // 错误, const char[6] 与 string是不同的类型
    return 0;
}

如果声明的是非引用参数,就可以使用长度不同的字符串作为max()的参数:

template<typename T>
inline T max(T x, T y)
{
    return x > y ? x : y;
}
int main(int, char**)
{
    ::max("hello", "world");    // 正确,具有相同的实参类型,const char[6],
                                // 这样在类型推导时都能匹配到同一个类型
    ::max("hello", "hell");     // 正确, decay(退化)为相同的类型
    std::string s("world");
    ::max("hello", s);          // 错误,不同的类型
    return 0;
}

产生在这种调用的原因是:对于非引用类型的参数,在实参演绎的过程中会出现数组到指针(pointer-to-array)的类型转换(这种转型通常也被称为decay),果真如此奇妙吗,我们不妨使用typeid关键字加以验证:

template<typename T>
void ref(const T& x)
{
    cout << "x in ref(const T&): " << typeid(x).name() << endl; 
}

template<typename T>
void noref(T x)
{
    cout << "x in noref(T): " << typeid(x).name() << endl;
}

int main(int, char**)
{
    ::ref("hello");             //  const char [6]
    ::noref("hello");           // const char*  
    return 0;
}

在上述的main函数中,分别将一个字符串(”hello”,类型为const char [6])传递给具有引用参数的函数模板和具有非引用参数的函数模板。通过打印的结果我们可以看到,参数为引用的函数模板和参数不是引用的函数模板在对待字符数组和字符串指针之间存在着一些隐蔽的不同。对这一问题并没有太好的方法,根据不同的情况,可以:

  • 使用非引用参数,取代引用参数,

    杀敌一千,自损八百,导致无用的拷贝

  • 重载版本1,分别编写参数为引用类型地函数模板,和参数为非引用类型的函数模板

    这可能会导致二义性的出现;

  • 重载版本2,重载数组类型

template<typename T, int N, int M>      // 存在两个非类型模板参数
inline const T* max(const T (*x)[N], const T (*y)[M])
{
    return x > y ? x : y;
}

事实上我们更倾向于使用,std::stringc++风格的字符串类,而不是c风格字符串类,这又牵涉到C++和C语言风格的问题了。C++是一种语言联邦,支持多编程范式。我们在之前的文章中有谈到,两种语言风格下的类型转换问题,<C++基础——C++风格的类型转换(static_cast、const_cast、dynamic_cast、reinterpret_cast>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五道口纳什

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值