第5章 技巧性基础:5.4 原始数组和字符串字面量的模板

5.4 Templates for Raw Arrays and String Literals

5.4 原始数组和字符串字面量的模板

 

When passing raw arrays or string literals to templates, some care has to be taken.First, if the template parameters are declared as references, the arguments don’t decay. That is, a passed argument of "hello" has type char const[6]. This can become a problem if raw arrays or string arguments of different length are passed because the types differ. Only when passing the argument by value, the types decay, so that string literals are converted to type char const*. This is discussed in detail in Chapter 7.

将原始数组或字符串字面量传递给模板时,必须格外小心。首先,如果将模板参数声明为引用,则参数不会退化(decay)。也就是说,如果传递实参 “hello”,则其类型将为char const[6]。由于类型不同,如果传递了不同长度的原始数组或字符串实参,这可能会成为问题。只有当按值传递时,类型才会退化(decay)。因此字符串字面量被转换为char const*类型,这将在第7章中详细讨论。

Note that you can also provide templates that specifically deal with raw arrays or string literals. For example:

注意,你也可以提供一个用于特殊处理原始数组或字符串字面量的模板。例如:

template<typename T, int N, int M>
bool less(T(&a)[N], T(&b)[M])
{
    for (int i = 0; i < N && i < M; ++i)
    {
        if (a[i] < b[i]) return true;
        if (b[i] < a[i]) return false;
    }
    return N < M;
}

Here, when calling

在此,当调用

int x[] = { 1, 2, 3 };
int y[] = { 1, 2, 3, 4, 5 };
std::cout << less(x, y) << '\n';

less<>() is instantiated with T being int, N being 3, and M being 5.

less<>()被实例化为:T为int类型,N为3,M为5。

You can also use this template for string literals:

你也可以将此模板应用于字符串字面量:

std::cout << less("ab", "abc") <<  '\n';

In this case, less<>() is instantiated with T being char const, N being 3 and M being 4.

在这种情况下,less<>()被实例化为:T为char const类型,N为3,为4。

If you only want to provide a function template for string literals (and other char arrays), you can do this as follows:

如果只想为字符串字面量(和其他字符数组)提供函数模板,也可以按如下去做:

template<int N, int M>
bool less(char const(&a)[N], char const(&b)[M])
{
    for (int i = 0; i < N && i < M; ++i) {
        if (a[i] < b[i]) return true;
        if (b[i] < a[i]) return false;
    }
return N < M; }

Note that you can and sometimes have to overload or partially specialize for arrays of unknown bounds. The following program illustrates all possible overloads for arrays:

注意,你可以,有时是必须重载或偏特化未知数量的数组。下面的程序演示了所有可能为数组进行的重载:

template<typename T>
struct MyClass; // 主模板

template<typename T, std::size_t SZ>
struct MyClass<T[SZ]> // 为未知数量的数组偏特化
{
    static void print() { std::cout << "print() for T[" << SZ << "]\n"; }
};

template<typename T, std::size_t SZ>
struct MyClass<T(&)[SZ]> //数组引用:为未知数量的数组偏特化
{
    static void print() { std::cout << "print() for T(&)[" << SZ << "]\n"; }
};

template<typename T>
struct MyClass<T[]> // 为未知数量的数组偏特化
{
    static void print() { std::cout << "print() for T[]\n"; }
};

template<typename T>
struct MyClass<T(&)[]> // 数组引用:
{
    static void print() {std::cout << "print() for T(&)[]\n"; }
};

template<typename T>
struct MyClass<T*> // 指针类型的偏特化
{
    static void print() { std::cout << "print() for T*\n"; }
};

Here, the class template MyClass<> is specialized for various types: arrays of known and unknown bound, references to arrays of known and unknown bounds, and pointers. Each case is different and can occur when using arrays:

此处,MyClass<>类模板特化为不同的类型:己知或未知数量的数组、对己知或未知数量数组的引用和指针。每种情况都是不同的,使用数组时都可能发生:

#include "arrays.hpp"

template<typename T1, typename T2, typename T3>
void foo(int a1[7], int a2[], // 根据语言规则,这里为指针类型
    int(&a3)[42], // 对己知数量数组的引用
    int(&x0)[], //对未知数量数组的引用
    T1 x1, // 按值传参,数型退化(decay)
    T2& x2, T3&& x3) // 按引用传参
{
    MyClass<decltype(a1)>::print(); // uses MyClass<T*>
    MyClass<decltype(a2)>::print(); // uses MyClass<T*>
    MyClass<decltype(a3)>::print(); // uses MyClass<T(&)[SZ]>
    MyClass<decltype(x0)>::print(); // uses MyClass<T(&)[]>
    MyClass<decltype(x1)>::print(); // uses MyClass<T*>
    MyClass<decltype(x2)>::print(); // uses MyClass<T(&)[]>
    MyClass<decltype(x3)>::print(); // uses MyClass<T(&)[]>
}

int main()
{
    int a[42];
    MyClass<decltype(a)>::print(); // uses MyClass<T[SZ]>
    extern int x[]; // forward declare array
    MyClass<decltype(x)>::print(); // uses MyClass<T[]>
    foo(a, a, a, x, x, x, x);
}

int x[] = { 1,2,3,4 };

Note that a call parameter declared as an array (with or without length) by language rules really has a pointer type. Note also that templates for arrays of unknown bounds can be used for an incomplete type such as

注意,根据语言规则,声明为数组(带或不带长度)的形参实际为指针类型。还要注意,未知数量的数组模板可以用于不完整的类型,例如

extern int i[];

And when this is passed by reference, it becomes a int(&)[], which can also be used as a template parameter.

同时,当通过引用传递时,它变成一个int(&)[],也可以用作模板参数。

See Section 19.3.1 on page 401 for another example using the different array types in generic code.

关于泛型代码中使用不同数组类型的另一个例子,请参阅第401页的19.3.1节。

上一篇:Yii PHP 框架分析 (一)


下一篇:js基石之---es7的decorator修饰器