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

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

#include 
#include 

template void f(T& param)
{
    using ParamType = T&;
    bool TIsArray = std::is_same::value;
    bool TIsConstCharPoint = std::is_same::value;
    if (TIsArray) {
        std::cout << "T is const char[13], ";
    } else if (TIsConstCharPoint) {
        std::cout << "T is const char*, ";
    }
    bool ParamTypeIsArrayRef = std::is_same::value;
    bool ParamTypeIsConstCharPointRef = std::is_same::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 
#include 

template void f(T&& param)
{
    using ParamType = T&&;
    bool TIsArray = std::is_same::value;
    bool TIsArrayRef = std::is_same::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::value;
    bool ParamTypeIsConstCharPointRef = std::is_same::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 
#include 

template void f(T param)
{
    using ParamType = T;
    bool TIsArray = std::is_same::value;
    bool TIsConstCharPoint = std::is_same::value;
    if (TIsArray) {
        std::cout << "T is const char[13], ";
    } else if (TIsConstCharPoint) {
        std::cout << "T is const char*, ";
    }
    bool ParamTypeIsArray = std::is_same::value;
    bool ParamTypeIsConstCharPoint = std::is_same::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 

template
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],编译会失败,原因是这个不是通用引用,而是右值引用。

你可能感兴趣的:(C/C++技术,c++,开发语言)