4.3 Application of Variadic Templates
4.3 可变参数模板的应用
Variadic templates play an important role when implementing generic libraries, such as the C++ standard library.
可变参数模板在实现通用库(如C++标准库)时扮演着一个非常重要的角色。
One typical application is the forwarding of a variadic number of arguments of arbitrary type.
一个经典的应用就是对数量不定的任意类型参数进行传发。
For example, we use this feature when:
例如,我们在以下几种情况下使用这个特性:
• Passing arguments to the constructor of a new heap object owned by a shared pointer:
将参数传递给shared_ptr所拥有的新堆对象的构造函数:
// create shared pointer to complex<float> initialized by 4.2 and 7.7: auto sp = std::make_shared<std::complex<float>>(4.2, 7.7);
• Passing arguments to a thread, which is started by the library:
将参数传递给由标准库启动的thread对象。
std::thread t (foo, 42, "hello"); //call foo(42,"hello") in a separate thread
• Passing arguments to the constructor of a new element pushed into a vector:
将参数传递给新压入的vector中的元素的构造函数:
std::vector<Customer> v; … v.emplace("Tim", "Jovi", 1962); //insert a Customer initialized by three arguments
Usually, the arguments are “perfectly forwarded” with move semantics (see Section 6.1 on page 91), so that the corresponding declarations are, for example:
通常,这些参数都会通过移动语义被“完美转发”(请参阅第91页的6.1节),因此相应的声明如下:
namespace std { template<typename T, typename... Args> shared_ptr<T> make_shared(Args&& … args); class thread { public: template<typename F, typename... Args> explicit thread(F&& f, Args&& … args); ... }; template<typename T, typename Allocator = allocator<T>> class vector { public: template<typename... Args> reference emplace_back(Args&& … args); ... }; }
Note also that the same rules apply to variadic function template parameters as for ordinary parameters. For example, if passed by value, arguments are copied and decay (e.g., arrays become pointers), while if passed by reference, parameters refer to the original parameter and don’t decay:
还要注意,与普通参数一样,可变函数模板参数也适用相同的规则。例如,如果按值传递,则复制参数并且类型会退化(decay)(如,数组变成指针)。而如果按引用传递,则参数会引用原始的参数而且类型不会退化(decay)。
// args are copies with decayed types:(args是退化后的参数副本) template<typename… Args> void foo (Args… args); // args are nondecayed references to passed objects:(args并没退化,是传入对象引用) template<typename… Args> void bar (Args const&… args);