第5章 技巧性基础:5.1 关键字typename

Chapter 5:Tricky Basics

第5章 技巧性基础知识

 

This chapter covers some further basic aspects of templates that are relevant to the practical use of templates: an additional use of the typename keyword, defining member functions and nested classes as templates, template template parameters, zero initialization, and some details about using string literals as arguments for function templates. These aspects can be tricky at times, but every day-to-day programmer should have heard of them.

本章给出模板的一些更深入的基础知识,它们都是和模板的实际应用密切相关的。包括关键字typename的另一种用法、把成员函数嵌套类也定义成模板、模板模板参数(template template parameters)、零初始化和使用字符串字面量作为函数模板的实参时所需要注意的一些细节。虽然这些技术具有很强的技巧性,但是每个日常的C++程序员对他们也应该略有耳闻了。

5.1 Keyword typename

5.1 关键字typename

 

The keyword typename was introduced during the standardization of C++ to clarify that an identifier inside a template is a type. Consider the following example:

在C++标准化过程中,引入关键字typename是为了说明:模板内部的标识符是一个类型。考虑下面的例子:

template<typename T>
class MyClass {
public:
    …
    void foo() {
        typename T::SubType* ptr;
    }
};

Here, the second typename is used to clarify that SubType is a type defined within class T. Thus, ptr is a pointer to the type T::SubType.

上面例子中,第2个typename被用来说明:SubType是定义在类T内部的一种类型。因此,ptr是一个指向T::SubType类型的指针。

Without typename, SubType would be assumed to be a nontype member (e.g., a static data member or an enumerator constant). As a result, the expression

如果不使用typename,SubType就会被认为是一个非类型成员(如,一个静态成员变量或是枚举常量)。结果,下面的表达会

T::SubType* ptr;

would be a multiplication of the static SubType member of class T with ptr, which is not an error, because for some instantiations of MyClass<> this could be valid code.

会被认为是类T的静态成员SubType和ptr的乘积。这不是错误,因为对于MyClass<>的某此实例,这可能是有效的代码。

In general, typename has to be used whenever a name that depends on a template parameter is a type. This is discussed in detail in Section 13.3.2 on page 228.

通常而言,当某个依赖于模板参数的名称是一个类型时,就应该使用typename。我们将在第228页的13.3.2节中详细讨论这个问题。

One application of typename is the declaration to iterators of standard containers in generic code:

typename的一个经典应用就是用通用代码来声明STL容器的迭代器:

#include <iostream>

// print elements of an STL container
template<typename T>
void printcoll (T const& coll)
{
    typename T::const_iterator pos; //用于迭代coll的迭代器
    typename T::const_iterator end(coll.end()); //结束位置
    
    for (pos=coll.begin(); pos!=end; ++pos) {
        std::cout << *pos << ' ';
    }
    
    std::cout << '\n';
}

In this function template, the call parameter is an standard container of type T. To iterate over all elements of the container, the iterator type of the container is used, which is declared as type const_iterator inside each standard container class:

在这个函数模板中,形参是一个T类型的STL容器。为了迭代容器中的所有元素,我们借助于迭代器类型:而在每个STL容器类中,都声明有迭代器类型const_iterator:

class stlcontainer {
public:
    using iterator = …; // 可以读写/访问的迭代器
    using const_iterator = …; //只读类型的迭代器
    …
};

Thus, to access type const_iterator of template type T, you have to qualify it with a leading typename:

因此,为了访问模板类型为T的const_iterator迭代器。你需要在声明的开始处使用typename来加以限定:

typename T::const_iterator pos;

See Section 13.3.2 on page 228 for more details about the need for typename until C++17.

有关在C++17之前需要typename的更多详细信息,请参阅第228页的13.3.2节。

 

Note that C++20 will probably remove the need for typename in many common cases (see Section 17.1 on page 354 for details).

注意,在许多常见的场合下,C++20可能会消除对typename的需求(有关详细信息,请参阅第354页的17.1节)

上一篇:JS继承 -- 寄生式继承 & 寄生组合式继承


下一篇:JavsScript继承