Mot*_*tti 24
最简单的一个例子是以下的实现max甚至没有在类型上模板化.
int maximum(int n)
{
return n;
}
template<typename... Args>
int maximum(int n, Args... args)
{
return max(n, maximum(args...));
}
Run Code Online (Sandbox Code Playgroud)
规范printf实现只是稍微复杂一些:
void printf(const char *s)
{
while (*s)
{
if (*s == '%' && *(++s) != '%')
throw "invalid format string: missing arguments";
std::cout << *s++;
}
}
template<typename T, typename... Args>
void printf(const char* s, T value, Args... args)
{
while (*s)
{
if (*s == '%' && *(++s) != '%')
{
std::cout << value;
printf(s, args...); // call even when *s == 0 to detect extra arguments
return;
}
std::cout << *s++;
}
throw "extra arguments provided to printf";
}
Run Code Online (Sandbox Code Playgroud)
sel*_*tze 11
可变参数模板是C++ 0x功能,主要针对通用库的作者.我不希望在"用户代码"中看到它们.例如,在C++ 0x标准库中,它们在很多地方使用:std :: function,std :: async,std :: reference_wrapper,std :: tuple,std :: packaged_task,...
给你举个例子,我会告诉你如何的reference_wrapper可能相对于可变参数模板来实现:
template<class T>
class reference_wrapper
{
T *ptr;
public:
explicit reference_wrapper(T& thing) : ptr(&thing) {}
explicit reference_wrapper(T&& ) = delete;
operator T&() const {return *ptr;}
template<class... Args>
decltype( declval<T&>()(declval<Args>()...) )
operator()(Args&&... args) const
{
return (*ptr)(forward<Args>(args)...);
}
};
Run Code Online (Sandbox Code Playgroud)
这并不完全符合标准草案,但它应该是可编译的,几乎没有修改.它演示了多个C++ 0x功能:
decltypedeclval,用于为构建表达式创建对象decltype(GCC尚未提供此函数模板.您必须自己编写)可变参数成员模板的目的是将参数转发给引用的对象ptr.这应该适用于T是函数指针类型或具有重载函数调用运算符的类类型的情况.
干杯!小号
可变参数模板的一个非常简单的例子:
假设我们想要一个函数,它接受可变数量的参数并将它们全部打印出来.例如:
print("Hello", 1, 3.14, 5L);
Run Code Online (Sandbox Code Playgroud)
要使该功能起作用,我们基本上需要两个功能:
第一个,一个带有可变数量参数的函数:
template<typename T, typename... Args>
void print(T t, Args ...args){
std::cout << t << ", ";
print(args...);
}
Run Code Online (Sandbox Code Playgroud)
一些解释:
1.)由省略号(...)表示的参数包,出现在参数列表中.
typename...Args
| | << Optional whitespace. Can have multiple whitespaces in between them
Args...args
Run Code Online (Sandbox Code Playgroud)
这意味着,这些都是一样的.
typename ...args
typename...args
typename ... args
Run Code Online (Sandbox Code Playgroud)
因此,您不必担心空白的正确位置.尽管如此,IMO最多应该使用一个空白作为最佳实践.
2.)包扩展:一个模式后跟省略号.
print(args...); //expand when you wish to use them
Run Code Online (Sandbox Code Playgroud)
3.)参数包接受零个或多个模板参数.所以,print(T t, Args... args)接受一个或多个 args.
一旦理解了这一点,我们就可以将呼叫流程可视化如下:
print("Hello", 1, 3.14, 5L);
Run Code Online (Sandbox Code Playgroud)
翻译成:
print(string, int, float, long);
Run Code Online (Sandbox Code Playgroud)
哪个叫
print(int, float, long);
Run Code Online (Sandbox Code Playgroud)
哪个叫
print(float, long); // say Level 2
Run Code Online (Sandbox Code Playgroud)
哪个叫
print(long); // say Level 1
Run Code Online (Sandbox Code Playgroud)
哪个叫
print(); // say Level 0
Run Code Online (Sandbox Code Playgroud)
如果你仔细地遵循了#3点,你必须意识到print(T t, Args... args)无法处理0级的调用.
所以我们需要另一个具有相同名称的函数来跟上任何级别> = 0.
第二个,一个在调用堆栈顶部获取调用的函数:
赶上0级:
void print(){}
Run Code Online (Sandbox Code Playgroud)
或者,在第1级抓住:
template<typename T>
void print(T t){ std::cout << t;}
Run Code Online (Sandbox Code Playgroud)
或者,在第2级抓住:
template<typename T, typename U>
void print(T t, U u){ std::cout << t << ", " << u;}
Run Code Online (Sandbox Code Playgroud)
等......
任何这些都可行.希望这能帮助你下次去写这样的功能或课程.
可变参数模板是 C++0x 标准的一部分,但尚未正式发布。从 4.3 版开始,gcc 支持它们,但您需要通过添加编译器开关 -std=c++0x 来启用对 C++0x 的支持。
| 归档时间: |
|
| 查看次数: |
13680 次 |
| 最近记录: |