现代C++技术研究(3)---模板类型推导(3)

本文讨论模板函数的输入参数是数组的场景。按照前文的分析,首先看第一种情况,也就是模板参数是引用或者是指针,但是不是通用引用:

#include <iostream>
#include <type_traits>

template<typename T> void f(T& param)
{
    using ParamType = T&;
    bool TIsArray = std::is_same<T, const char[13]>::value;
    bool TIsConstCharPoint = std::is_same<T, const char*>::value;
    if (TIsArray) {
        std::cout << "T is const char[13], ";
    } else if (TIsConstCharPoint) {
        std::cout << "T is const char*, ";
    }
    bool ParamTypeIsArrayRef = std::is_same<ParamType, const char (&)[13]>::value;
    bool ParamTypeIsConstCharPointRef = std::is_same<ParamType, const char*&>::value;
    if (ParamTypeIsArrayRef) {
        std::cout << "param's type is const char (&)[13]\n";
    } else if (ParamTypeIsConstCharPointRef) {
        std::cout << "param's type is const char*&\n";
    }
}

int main()
{
    const char name[] = "J. P. Briggs"; // name's type is const char[13]
    f(name); // T is const char[13], param's type is const char (&)[13]
    return 0;
}

可以看到,推导的结果,T是数组,而ParamType是数组的引用。这个符合预期。

第二种情况,模板参数是通用引用:

#include <iostream>
#include <type_traits>

template<typename T> void f(T&& param)
{
    using ParamType = T&&;
    bool TIsArray = std::is_same<T, const char[13]>::value;
    bool TIsArrayRef = std::is_same<T, const char (&)[13]>::value;
    if (TIsArray) {
        std::cout << "T is const char[13], ";
    } else if (TIsArrayRef) {
        std::cout << "T is const char (&)[13], ";
    }
    bool ParamTypeIsArrayRef = std::is_same<ParamType, const char (&)[13]>::value;
    bool ParamTypeIsConstCharPointRef = std::is_same<ParamType, const char*&>::value;
    if (ParamTypeIsArrayRef) {
        std::cout << "param's type is const char (&)[13]\n";
    } else if (ParamTypeIsConstCharPointRef) {
        std::cout << "param's type is const char*&\n";
    }
}

int main()
{
    const char name[] = "J. P. Briggs"; // name's type is const char[13]
    f(name); // T is const char (&)[13], param's type is const char (&)[13]
    return 0;
}

传入的数组是左值,因此T和ParamType相同,都是数组的引用。也符合预期。

第三种情况:模板参数既不是指针,也不是引用:

#include <iostream>
#include <type_traits>

template<typename T> void f(T param)
{
    using ParamType = T;
    bool TIsArray = std::is_same<T, const char[13]>::value;
    bool TIsConstCharPoint = std::is_same<T, const char*>::value;
    if (TIsArray) {
        std::cout << "T is const char[13], ";
    } else if (TIsConstCharPoint) {
        std::cout << "T is const char*, ";
    }
    bool ParamTypeIsArray = std::is_same<ParamType, const char[13]>::value;
    bool ParamTypeIsConstCharPoint = std::is_same<ParamType, const char*>::value;
    if (ParamTypeIsArray) {
        std::cout << "param's type is const char[13]\n";
    } else if (ParamTypeIsConstCharPoint) {
        std::cout << "param's type is const char*\n";
    }
}

int main()
{
    const char name[] = "J. P. Briggs"; // name's type is const char[13]
    f(name); // T is const char*, param's type is const char*
    return 0;
}

这种情况,T和ParamType相同,但退化为指针。

神奇的是,可以利用模板函数推导出数组的结果,在编译时计算数组的长度:

#include <iostream>

template<typename T, std::size_t N>
constexpr std::size_t arraySize(T (&)[N]) noexcept
{
    return N;
}

int main()
{
    int keyVals[] = { 1, 3, 7, 9, 11, 22, 35 }; // keyVals has 7 elements
    int KeyValsArrayNum = arraySize(keyVals);
    std::cout << "KeyValsArrayNum is " << KeyValsArrayNum << "\n"; // KeyValsArrayNum is 7
    return 0;
}

如果,把T(&)[N]改成T(&&)[N],编译会失败,原因是这个不是通用引用,而是右值引用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值