Rob Murray分析的Obfuscated C++, 不懂STL的人可能看不懂。

myan 2001-02-25 12:43:00
Obfuscated C++

Rob Murray

. Last Month's Obfuscated C++

Last month we asked you to explain the output of the following program:
#include
#include
using namespace std;

template
void g(int size, op o, const char* sep = "") {
for(int i = 0; i < size; ++i)
cout << o(i) << sep;
}

template
struct w {
char* operator()(int a) {
return g(size,binder1st(op(),a),"\t"),"\n";
}
};

template
void
x(){
g(size, w());
}

int main(){
x,6>();
return 0;
}

This constructor of the x template prints a multiplication table of six rows and six columns, for example:
0 0 0 0 0 0
0 1 2 3 4 5
0 2 4 6 8 10
0 3 6 9 12 15
0 4 8 12 16 20
0 5 10 15 20 25

To understand how this works, we'll first examine the template function g(size,op,sep). op is a function object. The function object is "called" with the first size integers (starting at 0) and the results printed (separated by the string specified by the optional sep argument). We use this function twice.

The first call is in the template function x. It calls g, passing size and an object of type w<op,size>. For our example, this will call g(6,w<multiplies<int>,6>,""), which will cause the following invocations to occur:
w<'multiplies<int>,6>::operator()(0); //rownum = 0
w<multiplies<int>,6>::operator()(1); //rownum = 1
...
w<multiplies<int>,6>::operator()(5); //rownum = 5

Each of these constructors prints a single row of the table. It does this by creating a new function object
binder1st<multiplies<int> >(multiplies(),rownum)

where rownum is the row being printed. This binder1st object is passed to g(), which invokes operator() on the object for each of the integers from 0 to size-1. This prints a single row of the table, using a tab as the separator argument.

binder1st is a standard template class defined in the <functional> header. It takes a binary function object (in this case, multiplies<int>) and a single operand, and creates a new unary function object that "binds" the operand as the first operand of the binary function. This resulting object is invoked by calling operator(), passing a single operand. operator() returns the result of applying the original binary function to the "bound" operand and the operand supplied at the call.

In our example, the row index is "bound" as the first operand. For each column, the invocation of the binder1st object invokes multiplies<int>(int,int), passing the row and column indices respectively; the result is printed by g.

For bonus credit: Explain how the newline at the end of each row is printed.

Parameterizing the operation as a function object allows us to generate tables for other operations. For instance, x<plus<int>,4>() gives us:
0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6




This Month's Obfuscated C++

This month's Obfuscated C++ tests your knowledge of some of the standard template libraries. What is the output of the following program?
#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>

struct {
void operator()(int i){cout<<i<<"\n";}
} c;
int main(){
list<int> il(2,1);
list<int>::iterator i1(il.begin()),i2(i1);i2++;
back_insert_iterator<list<int> >i3(il);
for(;*i1<20000;i1++,++i2)
*i3=*i1+*i2;
for_each(il.begin(),il.end(),c);
return 0;
}


...全文
208 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
myan 2001-02-25
  • 打赏
  • 举报
回复
始祖鸟老兄别怪, 我自己能作答的问题从来不给分. 不过,
um! 您的确是只老鸟!
第一个程序原文有问题, 我随后贴出正确程序.
ed9er 2001-02-25
  • 打赏
  • 举报
回复
um!20000这个值设的很好,打出来刚好一屏
ed9er 2001-02-25
  • 打赏
  • 举报
回复
没分?!算了,我来蒙第二个,是不是菲薄那吃数列?除非i++和++i的实现有很大差异,要不应该是的
vcmfc 2001-02-25
  • 打赏
  • 举报
回复
真的看不懂!
vcmfc 2001-02-25
  • 打赏
  • 举报
回复
真的看不懂!

15,440

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 非技术区
社区管理员
  • 非技术区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧